File Coverage

lib/B/DeparseTree/PP.pm
Criterion Covered Total %
statement 312 540 57.7
branch 102 210 48.5
condition 63 156 40.3
subroutine 67 112 59.8
pod 0 97 0.0
total 544 1115 48.7


line stmt bran cond sub pod time code
1             # Copyright (c) 2015, 2018 Rocky Bernstein
2              
3             # Common PP (push-pull) opcodes methods. Most of these are called
4             # from the method dispatch in Common.
5             #
6             # Specifc Perl versions can override these. Note some PP opcodes are
7             # handled via table lookup to their underlying base-handling function,
8             # e.g. binop, listop, unop, ....
9              
10 8     8   47 use strict;
  8         15  
  8         232  
11 8     8   44 use warnings ();
  8         17  
  8         350  
12             require feature;
13              
14             my %feature_keywords = (
15             # keyword => 'feature',
16             state => 'state',
17             say => 'say',
18             given => 'switch',
19             when => 'switch',
20             default => 'switch',
21             break => 'switch',
22             evalbytes=>'evalbytes',
23             __SUB__ => '__SUB__',
24             fc => 'fc',
25             );
26              
27 8     8   39 use rlib '../..';
  8         13  
  8         56  
28              
29             package B::DeparseTree::PP;
30              
31 8     8   2748 use B::DeparseTree::SyntaxTree;
  8         14  
  8         546  
32 8     8   43 use B::DeparseTree::OPflags;
  8         11  
  8         367  
33 8     8   42 use B::DeparseTree::PPfns;
  8         31  
  8         2002  
34 8     8   56 use B::DeparseTree::TreeNode;
  8         24  
  8         718  
35 8     8   134 use B::Deparse;
  8         15  
  8         1251  
36             our($VERSION, @EXPORT, @ISA);
37             $VERSION = '3.2.0';
38              
39             @ISA = qw(Exporter B::Deparse );
40              
41             # Copy unchanged functions from B::Deparse
42             *lex_in_scope = *B::Deparse::lex_in_scope;
43             *gv_or_padgv = *B::Deparse::gv_or_padgv;
44             *padany = *B::Deparse::padany;
45             *padname = *B::Deparse::padname;
46             *pp_anonhash = *B::Deparse::pp_anonhash;
47             *pp_anonlist = *B::Deparse::pp_anonlist;
48             *pp_i_negate = *B::Deparse::pp_i_negate;
49             *pp_negate = *B::Deparse::pp_negate;
50             *real_negate = *B::Deparse::real_negate;
51 8         1199 use B qw(
52             OPf_MOD OPpENTERSUB_AMPER
53             OPf_SPECIAL
54             OPf_STACKED
55             OPpEXISTS_SUB
56             OPpTRANS_COMPLEMENT
57             OPpTRANS_DELETE
58             OPpTRANS_SQUASH
59             SVf_POK
60             SVf_ROK
61             class
62             opnumber
63 8     8   51 );
  8         14  
64              
65             @EXPORT = qw(
66             feature_enabled
67             gv_or_padgv
68             pp_aelem
69             pp_aelemfast
70             pp_aelemfast_lex
71             pp_and
72             pp_anonhash
73             pp_anonlist
74             pp_aslice
75             pp_avalues
76             pp_backtick
77             pp_boolkeys
78             pp_clonecv
79             pp_cmp
80             pp_cond_expr
81             pp_connect
82             pp_const
83             pp_delete
84             pp_dofile
85             pp_entereval
86             pp_entersub
87             pp_eq
88             pp_exec
89             pp_exists
90             pp_exp
91             pp_flop
92             pp_ge
93             pp_gelem
94             pp_glob
95             pp_gt
96             pp_gv
97             pp_gvsv
98             pp_helem
99             pp_hslice
100             pp_i_cmp
101             pp_i_eq
102             pp_i_ge
103             pp_i_gt
104             pp_i_le
105             pp_i_lt
106             pp_i_ne
107             pp_i_negate
108             pp_introcv
109             pp_kvaslice
110             pp_kvhslice
111             pp_le
112             pp_leave
113             pp_leavegiven
114             pp_leaveloop
115             pp_leavetry
116             pp_leavewhen
117             pp_lineseq
118             pp_list
119             pp_lslice
120             pp_lt
121             pp_mapstart
122             pp_ne
123             pp_negate
124             pp_not
125             pp_null
126             pp_once
127             pp_open_dir
128             pp_or
129             pp_padcv
130             pp_pos
131             pp_preinc
132             pp_print
133             pp_prtf
134             pp_pushre
135             pp_qr
136             pp_rcatline
137             pp_readline
138             pp_refgen
139             pp_require
140             pp_rv2cv
141             pp_sassign
142             pp_scalar
143             pp_scmp
144             pp_scope
145             pp_seq
146             pp_sge
147             pp_sgt
148             pp_sle
149             pp_slt
150             pp_sne
151             pp_sockpair
152             pp_split
153             pp_smartmatch
154             pp_stringify
155             pp_stub
156             pp_subst
157             pp_substr
158             pp_trans
159             pp_transr
160             pp_truncate
161             pp_unstack
162             pp_values
163             pp_vec
164             pp_waitpid
165             pp_xor
166             );
167              
168             BEGIN {
169             # List version-specific constants here.
170             # Easiest way to keep this code portable between version looks to
171             # be to fake up a dummy constant that will never actually be true.
172 8     8   26 foreach (qw(OPpCONST_ARYBASE OPpEVAL_BYTES)) {
173 16         27 eval { import B $_ };
  16         3746  
174 8     8   51 no strict 'refs';
  8         11  
  8         483  
175 16 100       39 *{$_} = sub () {0} unless *{$_}{CODE};
  8         25  
  16         555  
176             }
177             }
178              
179 8     8   30 BEGIN { for (qw[ const stringify rv2sv list glob pushmark null aelem
180             nextstate dbstate rv2av rv2hv helem custom ]) {
181 112         41950 eval "sub OP_\U$_ () { " . opnumber($_) . "}"
182             }}
183              
184             sub feature_enabled {
185 27     27 0 63 my($self,$name) = @_;
186 27         42 my $hh;
187 27         61 my $hints = $self->{hints} & $feature::hint_mask;
188 27 100 100     110 if ($hints && $hints != $feature::hint_mask) {
    100          
189 6         65 $hh = B::Deparse::_features_from_bundle($hints);
190             }
191 7         16 elsif ($hints) { $hh = $self->{'hinthash'} }
192 27   66     3472 return $hh && $hh->{"feature_$feature_keywords{$name}"}
193             }
194              
195             # FIXME: These don't seem to be able to go into the table.
196             # PPfns calls pp_sockpair for example?
197 0     0 0 0 sub pp_avalues { unop(@_, "values") }
198 6     6 0 48 sub pp_exec { maybe_targmy(@_, \&listop, "exec") }
199 4     4 0 19 sub pp_exp { maybe_targmy(@_, \&unop, "exp") }
200 7     7 0 21 sub pp_leave { scopeop(1, @_); }
201 5     5 0 20 sub pp_lineseq { scopeop(0, @_); }
202             sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
203             sub pp_preinc { pfixop(@_, "++", 23) }
204 16     16 0 62 sub pp_print { indirop(@_, "print") }
205 13     13 0 33 sub pp_prtf { indirop(@_, "printf") }
206 2     2 0 6 sub pp_sockpair { listop(@_, "socketpair") }
207 0     0 0 0 sub pp_values { unop(@_, "values") }
208 0     0 0 0 sub pp_pushre { matchop(@_, "m", "/") } # Is also in OP_PP table
209 0     0 0 0 sub pp_qr { matchop(@_, "qr", "") } # Is also in OP_PP table
210              
211             # Convert these to table entries...
212 0     0 0 0 sub pp_aelem { maybe_local(@_, elem(@_, "[", "]", "padav")) }
213 1     1 0 7 sub pp_aslice { maybe_local(@_, slice(@_, "[", "]", "rv2av", "padav")) }
214 0     0 0 0 sub pp_cmp { binop(@_, "<=>", 14) }
215 0     0 0 0 sub pp_eq { binop(@_, "==", 14) }
216 0     0 0 0 sub pp_ge { binop(@_, ">=", 15) }
217 0     0 0 0 sub pp_gt { binop(@_, ">", 15) }
218 1     1 0 6 sub pp_helem { maybe_local(@_, elem(@_, "{", "}", "padhv")) }
219 1     1 0 5 sub pp_hslice { maybe_local(@_, slice(@_, "{", "}", "rv2hv", "padhv")) }
220 0     0 0 0 sub pp_i_cmp { maybe_targmy(@_, \&binop, "<=>", 14) }
221 0     0 0 0 sub pp_i_eq { binop(@_, "==", 14) }
222 0     0 0 0 sub pp_i_ge { binop(@_, ">=", 15) }
223 0     0 0 0 sub pp_i_gt { binop(@_, ">", 15) }
224 0     0 0 0 sub pp_i_le { binop(@_, "<=", 15) }
225 0     0 0 0 sub pp_i_lt { binop(@_, "<", 15) }
226 0     0 0 0 sub pp_i_ne { binop(@_, "!=", 14) }
227 0     0 0 0 sub pp_kvaslice { slice(@_, "[", "]", "rv2av", "padav") }
228 0     0 0 0 sub pp_kvhslice { slice(@_, "{", "}", "rv2hv", "padhv") }
229 0     0 0 0 sub pp_le { binop(@_, "<=", 15) }
230 0     0 0 0 sub pp_lt { binop(@_, "<", 15) }
231 0     0 0 0 sub pp_ne { binop(@_, "!=", 14) }
232              
233 14     14 0 65 sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }
234 6     6 0 23 sub pp_scmp { binop(@_, "cmp", 14) }
235 4     4 0 20 sub pp_seq { binop(@_, "eq", 14) }
236 4     4 0 15 sub pp_sge { binop(@_, "ge", 15) }
237 4     4 0 14 sub pp_sgt { binop(@_, "gt", 15) }
238 4     4 0 14 sub pp_sle { binop(@_, "le", 15) }
239 4     4 0 13 sub pp_slt { binop(@_, "lt", 15) }
240 4     4 0 24 sub pp_sne { binop(@_, "ne", 14) }
241              
242             sub pp_aelemfast
243             {
244 1     1 0 4 my($self, $op, $cx) = @_;
245             # optimised PADAV, pre 5.15
246 1 50       9 return $self->pp_aelemfast_lex(@_) if ($op->flags & OPf_SPECIAL);
247              
248 1         13 my $gv = $self->gv_or_padgv($op);
249 1         38 my($name,$quoted) = $self->stash_variable_name('@',$gv);
250 1 50       7 $name = $quoted ? "$name->" : '$' . $name;
251 1         6 my $i = $op->private;
252 1 50       6 $i -= 256 if $i > 127;
253 1         13 return info_from_list($op, $self, [$name, "[", ($op->private + $self->{'arybase'}), "]"],
254             '', 'pp_aelemfast', {});
255             }
256              
257             sub pp_aelemfast_lex
258             {
259 2     2 0 8 my($self, $op, $cx) = @_;
260 2         73 my $name = $self->padname($op->targ);
261 2         17 $name =~ s/^@/\$/;
262 2         28 return info_from_list($op, $self, [$name, "[", ($op->private + $self->{'arybase'}), "]"],
263             '', 'pp_aelemfast_lex', {});
264             }
265              
266             sub pp_backtick
267             {
268 3     3 0 12 my($self, $op, $cx) = @_;
269             # skip pushmark if it exists (readpipe() vs ``)
270 3 50       48 my $child = $op->first->sibling->isa('B::NULL')
271             ? $op->first : $op->first->sibling;
272 3 50       23 if ($self->pure_string($child)) {
273 0         0 return $self->single_delim($op, "qx", '`', $self->dq($child, 1)->{text});
274             }
275 3         19 unop($self, $op, $cx, "readpipe");
276             }
277              
278             sub pp_boolkeys
279             {
280             # no name because its an optimisation op that has no keyword
281 0     0 0 0 unop(@_,"");
282             }
283              
284             sub pp_dofile
285             {
286 3     3 0 13 my $code = unop(@_, "do", 1); # llafr does not apply
287 3 50       22 if ($code =~ s/^((?:CORE::)?do) \{/$1({/) { $code .= ')' }
  0         0  
288 3         9 $code;
289             }
290              
291             sub pp_gelem
292             {
293 0     0 0 0 my($self, $op, $cx) = @_;
294 0         0 my($rv2gv, $part) = ($op->first, $op->last);
295 0         0 my $glob = $rv2gv->first; # skip rv2gv
296 0 0       0 $glob = $glob->first if $glob->name eq "rv2gv"; # this one's a bug
297 0         0 my $scope = B::Deparse::is_scope($glob);
298 0         0 my $glob_node = $self->deparse($glob, 0);
299 0         0 my $part_node = $self->deparse($part, 1);
300 0 0       0 my $fmt = ($scope ? '*{%c}{%c}' : '*%c{%c}');
301             # FIXME: fill in $rv2gv and possibly other node skipped above.
302 0         0 return $self->info_from_template("gelem *", $fmt, undef,
303             [$glob_node, $part_node],
304             {other_ops => [$rv2gv]});
305             }
306              
307 0     0 0 0 sub pp_leavegiven { givwhen(@_, $_[0]->keyword("given")); }
308 0     0 0 0 sub pp_leavewhen { givwhen(@_, $_[0]->keyword("when")); }
309              
310             sub pp_lslice
311             {
312 1     1 0 6 my ($self, $op, $cs) = @_;
313 1         9 my $idx = $op->first;
314 1         7 my $list = $op->last;
315 1         4 my(@elems, $kid);
316 1         5 my $list_info = $self->deparse($list, 1, $op);
317 1         5 my $idx_info = $self->deparse($idx, 1, $op);
318 1         6 return $self->info_from_template('lslice ()[]',
319             $op, '(%c)[%c]', undef,
320             [$list_info, $idx_info]);
321             }
322              
323 8     8 0 40 sub pp_pos { maybe_local(@_, unop(@_, "pos")) }
324              
325             sub pp_not
326             {
327 27     27 0 97 my($self, $op, $cx) = @_;
328 27 50       97 if ($cx <= 4) {
329 27         212 $self->listop($op, $cx, "not", $op->first);
330             } else {
331 0         0 $self->pfixop($op, $cx, "!", 21);
332             }
333             }
334              
335              
336             # skip down to the old, ex-rv2cv
337             sub pp_rv2cv {
338 0     0 0 0 my ($self, $op, $cx) = @_;
339 0 0 0     0 if (!B::Deparse::null($op->first) && $op->first->name eq 'null' &&
      0        
340             $op->first->targ == OP_LIST)
341             {
342 0         0 return $self->rv2x($op->first->first->sibling, $cx, "&")
343             }
344             else {
345 0         0 return $self->rv2x($op, $cx, "")
346             }
347             }
348              
349              
350             sub pp_scalar
351             {
352 4     4 0 9 my($self, $op, $cx) = @_;
353 4         12 my $kid = $op->first;
354 4 50       31 if (not B::Deparse::null $kid->sibling) {
355             # XXX Was a here-doc
356 0         0 return $self->dquote($op);
357             }
358 4         17 $self->unop($op, $cx, "scalar");
359             }
360              
361             sub pp_smartmatch {
362 0     0 0 0 my ($self, $op, $cx) = @_;
363 0 0       0 if ($op->flags & OPf_SPECIAL) {
364 0         0 my $child = $self->deparse($op->last, $cx, $op);
365 0         0 return $self->info_from_template('~~ special',
366             '%c', undef, [$child]);
367             } else {
368 0         0 binop(@_, "~~", 14);
369             }
370             }
371              
372             # Truncate is special because OPf_SPECIAL makes a bareword first arg
373             # be a filehandle. This could probably be better fixed in the core
374             # by moving the GV lookup into ck_truc.
375              
376             sub pp_truncate
377             {
378 2     2 0 5 my($self, $op, $cx) = @_;
379 2         4 my(@exprs);
380 2   33     6 my $parens = ($cx >= 5) || $self->{'parens'};
381 2         9 my $opts = {'other_ops' => [$op->first]};
382 2         9 my $kid = $op->first->sibling;
383 2         3 my $fh;
384 2 50       21 if ($op->flags & B::OPf_SPECIAL) {
385             # $kid is an OP_CONST
386 0         0 $fh = $self->const_sv($kid)->PV;
387             } else {
388 2         8 $fh = $self->deparse($kid, 6, $op);
389 2 50 33     16 $fh = "+$fh" if not $parens and substr($fh, 0, 1) eq "(";
390             }
391 2         19 my $len = $self->deparse($kid->sibling, 6, $op);
392 2         55 my $name = $self->keyword('truncate');
393 2         8 my $args = "$fh->{text}, $len->{text}";
394 2 50       14 if ($parens) {
395 2         22 return info_from_list($op, $self, [$name, '(', $args, ')'], '',
396             'truncate_parens', $opts);
397             } else {
398 0         0 return info_from_list($op, $self, [$name, $args], '', 'truncate', $opts);
399             }
400             }
401              
402 2     2 0 8 sub pp_vec { maybe_local(@_, listop(@_, "vec")) }
403              
404             sub pp_glob
405             {
406 2     2 0 6 my($self, $op, $cx) = @_;
407              
408 2         19 my $opts = {other_ops => [$op->first]};
409 2         14 my $kid = $op->first->sibling; # skip pushmark
410 2 50       48 my $keyword =
411             $op->flags & OPf_SPECIAL ? 'glob' : $self->keyword('glob');
412              
413 2 50 33     16 if ($keyword =~ /^CORE::/ or $kid->name ne 'const') {
414 2         10 my $kid_info = $self->dq($kid, $op);
415 2         5 my $body = [$kid_info];
416 2         6 my $text = $kid_info->{text};
417 2 50 33     22 if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline
418             or $text =~ /[<>]/) {
419 2         10 $kid_info = $self->deparse($kid, 0, $op);
420 2         8 $body = [$kid_info];
421 2         5 $text = $kid_info->{text};
422 2         3 $opts->{body} = $body;
423 2 50 33     20 if ($cx >= 5 || $self->{'parens'}) {
424             # FIXME: turn into template
425 0         0 return info_from_list($op, $self, [$keyword, '(', $text, ')'], '',
426             'glob_paren', $opts);
427             } else {
428             # FIXME: turn into template
429 2         11 return info_from_list($op, $self, [$keyword, $text], ' ',
430             'glob_space', $opts);
431             }
432             } else {
433 0         0 return $self->info_from_template('', $op, '<%c>', undef,
434             [$kid_info], $opts);
435             }
436             }
437 0         0 return $self->info_from_string("<>", $op, $opts);
438             }
439              
440             sub pp_clonecv {
441 0     0 0 0 my $self = shift;
442 0         0 my($op, $cx) = @_;
443 0         0 my $sv = $self->padname_sv($op->targ);
444 0         0 my $name = substr $sv->PVX, 1; # skip &/$/@/%, like $self->padany
445 0         0 return $self->info_from_string("clonev my sub", $op, "my sub $name");
446             }
447              
448             sub pp_delete($$$)
449             {
450 0     0 0 0 my($self, $op, $cx) = @_;
451 0         0 my $arg;
452 0         0 my ($info, $body, $type);
453 0 0       0 if ($op->private & B::OPpSLICE) {
454 0 0       0 if ($op->flags & B::OPf_SPECIAL) {
455             # Deleting from an array, not a hash
456 0         0 $info = $self->pp_aslice($op->first, 16);
457 0         0 $type = 'delete slice';
458             }
459             } else {
460 0 0       0 if ($op->flags & B::OPf_SPECIAL) {
461             # Deleting from an array, not a hash
462 0         0 $info = $self->pp_aelem($op->first, 16);
463 0         0 $type = 'delete array'
464             } else {
465 0         0 $info = $self->pp_helem($op->first, 16);
466 0         0 $type = 'delete hash';
467             }
468             }
469             my @texts = $self->maybe_parens_func("delete",
470 0         0 $info->{text}, $cx, 16);
471 0         0 return info_from_list($op, $self, \@texts, '', $type, {body => [$info]});
472             }
473              
474             sub pp_exists
475             {
476 0     0 0 0 my($self, $op, $cx) = @_;
477 0         0 my ($info, $type);
478 0         0 my $name = $self->keyword("exists");
479 0 0       0 if ($op->private & OPpEXISTS_SUB) {
    0          
480             # Checking for the existence of a subroutine
481 0         0 $info = $self->pp_rv2cv($op->first, 16);
482 0         0 $type = 'exists sub';
483             } elsif ($op->flags & OPf_SPECIAL) {
484             # Array element, not hash helement
485 0         0 $info = $self->pp_aelem($op->first, 16);
486 0         0 $type = 'exists array';
487             } else {
488 0         0 $info = $self->pp_helem($op->first, 16);
489 0         0 $type = 'exists hash';
490             }
491 0         0 my @texts = $self->maybe_parens_func($name, $info->{text}, $cx, 16);
492 0         0 return info_from_list($op, $self, \@texts, '', $type, {});
493             }
494              
495             sub pp_introcv
496             {
497 0     0 0 0 my($self, $op, $cx) = @_;
498             # For now, deparsing doesn't worry about the distinction between introcv
499             # and clonecv, so pretend this op doesn't exist:
500 0         0 return info_from_text($op, $self, '', 'introcv', {});
501             }
502              
503 5     5 0 26 sub pp_leaveloop { shift->loop_common(@_, undef); }
504              
505             sub pp_leavetry {
506 0     0 0 0 my ($self, $op, $cx) = @_;
507 0         0 my $leave_info = $self->pp_leave($op, $cx);
508 0         0 return $self->info_from_template('eval {}', $op, "eval {\n%+%c\n%-}",
509             undef, [$leave_info]);
510             }
511              
512             sub pp_list
513             {
514 3243     3243 0 5611 my($self, $op, $cx) = @_;
515 3243         4144 my($expr, @exprs);
516              
517 3243         9242 my $pushmark_op = $op->first;
518 3243         9148 my $kid = $pushmark_op->sibling; # skip a pushmark
519 3243         6248 my @other_ops = ($pushmark_op);
520              
521 3243 100       16753 if (class($kid) eq 'NULL') {
522 1         9 return info_from_text($op, $self, '', 'list_null',
523             {other_ops => \@other_ops});
524             }
525 3242         5406 my $lop;
526 3242         4344 my $local = "either"; # could be local(...), my(...), state(...) or our(...)
527 3242         17445 for ($lop = $kid; !B::Deparse::null($lop); $lop = $lop->sibling) {
528             # This assumes that no other private flags equal 128, and that
529             # OPs that store things other than flags in their op_private,
530             # like OP_AELEMFAST, won't be immediate children of a list.
531             #
532             # OP_ENTERSUB and OP_SPLIT can break this logic, so check for them.
533             # I suspect that open and exit can too.
534             # XXX This really needs to be rewritten to accept only those ops
535             # known to take the OPpLVAL_INTRO flag.
536              
537 5750 100 100     36918 if (!($lop->private & (B::Deparse::OPpLVAL_INTRO|B::Deparse::OPpOUR_INTRO)
      66        
538             or $lop->name eq "undef")
539             or $lop->name =~ /^(?:entersub|exit|open|split)\z/)
540             {
541 2586         4099 $local = ""; # or not
542 2586         4009 last;
543             }
544 3164 100 33     12558 if ($lop->name =~ /^pad[ash]v$/) {
    100 66        
    100 100        
      33        
      33        
      66        
545 3141 100       8482 if ($lop->private & B::Deparse::OPpPAD_STATE) { # state()
546 10 50       49 ($local = "", last) if $local =~ /^(?:local|our|my)$/;
547 10         103 $local = "state";
548             } else { # my()
549 3131 50       5897 ($local = "", last) if $local =~ /^(?:local|our|state)$/;
550 3131         20183 $local = "my";
551             }
552             } elsif ($lop->name =~ /^(gv|rv2)[ash]v$/
553             && $lop->private & B::Deparse::OPpOUR_INTRO
554             or $lop->name eq "null" && $lop->first->name eq "gvsv"
555             && $lop->first->private & B::Deparse::OPpOUR_INTRO) { # our()
556 12 50       46 ($local = "", last) if $local =~ /^(?:my|local|state)$/;
557 12         134 $local = "our";
558             } elsif ($lop->name ne "undef"
559             # specifically avoid the "reverse sort" optimisation,
560             # where "reverse" is nullified
561             && !($lop->name eq 'sort' && ($lop->flags & B::Deparse::OPpSORT_REVERSE)))
562             {
563             # local()
564 2 50       11 ($local = "", last) if $local =~ /^(?:my|our|state)$/;
565 2         22 $local = "local";
566             }
567             }
568 3242 100       6813 $local = "" if $local eq "either"; # no point if it's all undefs
569 3242 100 100     24473 if (B::Deparse::null $kid->sibling and not $local) {
570 2566         6901 my $info = $self->deparse($kid, $cx, $op);
571 2566         7308 $info->update_other_ops($pushmark_op);
572 2566         7943 return $info;
573             }
574              
575 676         3881 for (; !B::Deparse::null($kid); $kid = $kid->sibling) {
576 3241 100       6024 if ($local) {
577 3156 100 66     13711 if (class($kid) eq "UNOP" and $kid->first->name eq "gvsv") {
578 14         32 push @other_ops, $kid;
579 14         45 $lop = $kid->first;
580             } else {
581 3142         4725 $lop = $kid;
582             }
583 3156         7003 $self->{'avoid_local'}{$$lop}++;
584 3156         7619 $expr = $self->deparse($kid, 6, $op);
585 3156         6915 delete $self->{'avoid_local'}{$$lop};
586             } else {
587 85         302 $expr = $self->deparse($kid, 6, $op);
588             }
589 3241         32735 push @exprs, $expr;
590             }
591              
592 676 100       2113 if ($local) {
593 648         5750 return $self->info_from_template("$local ()", $op,
594             "$local(%C)", [[0, $#exprs, ', ']],
595             \@exprs, {other_ops => \@other_ops});
596              
597             } else {
598 28         264 return $self->info_from_template("list", $op,
599             "%C", [[0, $#exprs, ', ']],
600             \@exprs,
601             {maybe_parens => [$self, $cx, 6],
602             other_ops => \@other_ops});
603             }
604             }
605              
606             sub pp_padcv($$$) {
607 0     0 0 0 my($self, $op, $cx) = @_;
608 0         0 return info_from_text($op, $self, $self->padany($op), 'padcv', {});
609             }
610              
611             sub pp_refgen
612             {
613 2     2 0 8 my($self, $op, $cx) = @_;
614 2         14 my $kid = $op->first;
615 2 50       15 if ($kid->name eq "null") {
616 2         6 my $other_ops = [$kid];
617 2         7 my $anoncode = $kid = $kid->first;
618 2 50       23 if ($anoncode->name eq "anonconst") {
619 0         0 $anoncode = $anoncode->first->first->sibling;
620             }
621 2 50 0     33 if ($anoncode->name eq "anoncode"
    0 33        
622             or !B::Deparse::null($anoncode = $kid->sibling) and
623             $anoncode->name eq "anoncode") {
624 2         41 return $self->e_anoncode({ code => $self->padval($anoncode->targ) });
625             } elsif ($kid->name eq "pushmark") {
626 0         0 my $sib_name = $kid->sibling->name;
627 0 0       0 if ($sib_name =~ /^enter(xs)?sub/) {
628 0         0 my $kid_info = $self->deparse($kid->sibling, 1, $op);
629             # Always show parens for \(&func()), but only with -p otherwise
630 0         0 my @texts = ('\\', $kid_info->{text});
631 0 0 0     0 if ($self->{'parens'} or $kid->sibling->private & OPpENTERSUB_AMPER) {
632 0         0 @texts = ('(', "\\", $kid_info->{text}, ')');
633             }
634 0         0 return info_from_list($op, $self, \@texts, '', 'refgen_entersub',
635             {body => [$kid_info],
636             other_ops => $other_ops});
637             }
638             }
639             }
640 0         0 local $self->{'in_refgen'} = 1;
641 0         0 $self->pfixop($op, $cx, "\\", 20);
642             }
643              
644             sub pp_require
645             {
646 2     2 0 19 my($self, $op, $cx) = @_;
647 2 50       17 my $opname = $op->flags & OPf_SPECIAL ? 'CORE::require' : 'require';
648 2 50 66     49 if (class($op) eq "UNOP" and $op->first->name eq "const"
      66        
649             and $op->first->private & B::OPpCONST_BARE) {
650 0         0 my $name = $self->const_sv($op->first)->PV;
651 0         0 $name =~ s[/][::]g;
652 0         0 $name =~ s/\.pm//g;
653 0         0 return info_from_list($op, $self, [$opname, $name], ' ',
654             'require',
655             {maybe_parens => [$self, $cx, 16]});
656             } else {
657 2 50 66     37 return $self->unop(
658             $op, $cx,
659             $op->first->name eq 'const'
660             && $op->first->private & B::OPpCONST_NOVER
661             ? "no"
662             : $opname,
663             1, # llafr does not apply
664             );
665             }
666 0         0 Carp::confess("unhandled condition in pp_require");
667             }
668              
669              
670 0     0 0 0 sub pp_scope { scopeop(0, @_); }
671 46     46 0 185 sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }
672              
673             sub pp_cond_expr
674             {
675 0     0 0 0 my $self = shift;
676 0         0 my($op, $cx) = @_;
677 0         0 my $cond = $op->first;
678 0         0 my $true = $cond->sibling;
679 0         0 my $false = $true->sibling;
680 0         0 my $cuddle = $self->{'cuddle'};
681 0         0 my $type = 'if';
682 0 0 0     0 unless ($cx < 1 and (B::Deparse::is_scope($true) and $true->name ne "null") and
      0        
      0        
      0        
      0        
683             (B::Deparse::is_scope($false) || B::Deparse::is_ifelse_cont($false))
684             and $self->{'expand'} < 7) {
685             # FIXME: turn into template
686 0         0 my $cond_info = $self->deparse($cond, 8, $op);
687 0         0 my $true_info = $self->deparse($true, 6, $op);
688 0         0 my $false_info = $self->deparse($false, 8, $op);
689 0         0 return $self->info_from_template('ternary ?', $op, "%c ? %c : %c",
690             [0, 1, 2],
691             [$cond_info, $true_info, $false_info],
692             {maybe_parens => [$self, $cx, 8]});
693             }
694              
695 0         0 my $cond_info = $self->deparse($cond, 1, $op);
696 0         0 my $true_info = $self->deparse($true, 0, $op);
697 0         0 my $fmt = "%|if (%c) {\n%+%c\n%-}";
698 0         0 my @exprs = ($cond_info, $true_info);
699 0         0 my @args_spec = (0, 1);
700              
701 0         0 my $i;
702 0   0     0 for ($i=0; !B::Deparse::null($false) and B::Deparse::is_ifelse_cont($false); $i++) {
703 0         0 my $newop = $false->first;
704 0         0 my $newcond = $newop->first;
705 0         0 my $newtrue = $newcond->sibling;
706 0         0 $false = $newtrue->sibling; # last in chain is OP_AND => no else
707 0 0       0 if ($newcond->name eq "lineseq")
708             {
709             # lineseq to ensure correct line numbers in elsif()
710             # Bug #37302 fixed by change #33710.
711 0         0 $newcond = $newcond->first->sibling;
712             }
713 0         0 my $newcond_info = $self->deparse($newcond, 1, $op);
714 0         0 my $newtrue_info = $self->deparse($newtrue, 0, $op);
715 0         0 push @args_spec, scalar(@args_spec), scalar(@args_spec)+1;
716 0         0 push @exprs, $newcond_info, $newtrue_info;
717 0         0 $fmt .= " elsif ( %c ) {\n%+%c\n\%-}";
718             }
719 0 0       0 $type .= " elsif($i)" if $i;
720 0         0 my $false_info;
721 0 0       0 if (!B::Deparse::null($false)) {
722 0         0 $false_info = $self->deparse($false, 0, $op);
723 0         0 $fmt .= "${cuddle}else {\n%+%c\n%-}";
724 0         0 push @args_spec, scalar(@args_spec);
725 0         0 push @exprs, $false_info;
726 0         0 $type .= ' else';
727             }
728 0         0 return $self->info_from_template($type, $op, $fmt, \@args_spec, \@exprs);
729             }
730              
731             sub pp_const {
732 86     86 0 179 my $self = shift;
733 86         207 my($op, $cx) = @_;
734 86 50       480 if ($op->private & OPpCONST_ARYBASE) {
735 0         0 return info_from_text($op, $self, '$[', 'const_ary', {});
736             }
737             # if ($op->private & OPpCONST_BARE) { # trouble with '=>' autoquoting
738             # return $self->const_sv($op)->PV;
739             # }
740 86         615 my $sv = $self->const_sv($op);
741 86         323 return $self->const($sv, $cx);;
742             }
743              
744             # Handle subroutine calls. These are a bit complicated.
745             # NOTE: this is not right for CPerl, so it needs to be split out.
746             sub pp_entersub
747             {
748 576     576 0 1404 my($self, $op, $cx) = @_;
749 576 100       5916 return $self->e_method($op, $self->_method($op, $cx))
750             unless B::Deparse::null $op->first->sibling;
751 574         1663 my $prefix = "";
752 574         914 my $amper = "";
753 574         1074 my($kid, @exprs, @args_spec);
754 574 50 33     3968 if ($op->flags & OPf_SPECIAL && !($op->flags & OPf_MOD)) {
    50          
755 0         0 $prefix = "do ";
756             } elsif ($op->private & OPpENTERSUB_AMPER) {
757 0         0 $amper = "&";
758             }
759              
760 574         1815 $kid = $op->first;
761              
762 574         2225 my $other_ops = [$kid, $kid->first];
763 574         2585 $kid = $kid->first->sibling; # skip ex-list, pushmark
764              
765 574         1080 my $kid_start = $kid;
766             # FIXME: phase this out.
767 574         4549 for (; not B::Deparse::null $kid->sibling; $kid = $kid->sibling) {
768 722         5937 push @exprs, $kid;
769             }
770 574         1796 my ($simple, $proto, $subname_info) = (0, undef, undef);
771 574 50 0     15656 if (B::Deparse::is_scope($kid)) {
    50          
    0          
772 0         0 $amper = "&";
773 0         0 $subname_info = $self->deparse($kid, 0, $op);
774 0         0 $subname_info->{texts} = ['{', $subname_info->texts, '}'];
775 0         0 $subname_info->{text} = join('', @$subname_info->{texts});
776             } elsif ($kid->first->name eq "gv") {
777 574         7347 my $gv = $self->gv_or_padgv($kid->first);
778 574         1090 my $cv;
779 574 100 66     7067 if (class($gv) eq 'GV' && class($cv = $gv->CV) ne "SPECIAL"
      33        
      66        
780             || $gv->FLAGS & SVf_ROK && class($cv = $gv->RV) eq 'CV') {
781 540 100       1913 $proto = $cv->PV if $cv->FLAGS & SVf_POK;
782             }
783 574         970 $simple = 1; # only calls of named functions can be prototyped
784 574         1809 $subname_info = $self->deparse($kid, 24, $op);
785 574         902 my $fq;
786             # Fully qualify any sub name that conflicts with a lexical.
787 574 50 33     10721 if ($self->lex_in_scope("&$kid")
    50          
788             || $self->lex_in_scope("&$kid", 1))
789             {
790 0         0 $fq++;
791             } elsif (!$amper) {
792 574 50       1820 if ($subname_info->{text} eq 'main::') {
793 0         0 $subname_info->{text} = '::';
794             } else {
795 574 50 33     2867 if ($kid !~ /::/ && $kid ne 'x') {
796             # Fully qualify any sub name that is also a keyword. While
797             # we could check the import flag, we cannot guarantee that
798             # the code deparsed so far would set that flag, so we qual-
799             # ify the names regardless of importation.
800 0 0       0 if (exists $feature_keywords{$kid}) {
    0          
801 0 0       0 $fq++ if $self->feature_enabled($kid);
802 0         0 } elsif (do { local $@; local $SIG{__DIE__};
  0         0  
803 0         0 eval { () = prototype "CORE::$kid"; 1 } }) {
  0         0  
  0         0  
804 0         0 $fq++
805             }
806             }
807             }
808 574 50       4041 if ($subname_info->{text} !~ /^(?:\w|::)(?:[\w\d]|::(?!\z))*\z/) {
809 0         0 $subname_info->{text} = $self->single_delim($$kid, "q", "'", $kid) . '->';
810             }
811             }
812             } elsif (B::Deparse::is_scalar ($kid->first) && $kid->first->name ne 'rv2cv') {
813 0         0 $amper = "&";
814 0         0 $subname_info = $self->deparse($kid, 24, $op);
815             } else {
816 0         0 $prefix = "";
817 0 0 0     0 my $arrow = B::Deparse::is_subscriptable($kid->first)
818             || $kid->first->name eq "padcv" ? "" : "->";
819 0         0 $subname_info = $self->deparse($kid, 24, $op);
820 0         0 $subname_info->{text} .= $arrow;
821             }
822              
823             # Doesn't matter how many prototypes there are, if
824             # they haven't happened yet!
825 574         1206 my $declared;
826 574         1209 my $sub_name = $subname_info->{text};
827             {
828 8     8   76 no strict 'refs';
  8         19  
  8         284  
  574         855  
829 8     8   44 no warnings 'uninitialized';
  8         21  
  8         12160  
830             $declared = exists $self->{'subs_declared'}{$sub_name}
831             || (
832             defined &{ ${$self->{'curstash'}."::"}{$sub_name} }
833             && !exists
834             $self->{'subs_deparsed'}{$self->{'curstash'}."::" . $sub_name}
835 574   66     2084 && defined prototype $self->{'curstash'}."::" . $sub_name
836             );
837 574 50 66     2691 if (!$declared && defined($proto)) {
838             # Avoid "too early to check prototype" warning
839 0         0 ($amper, $proto) = ('&');
840             }
841             }
842              
843 574         1273 my (@texts, @nodes, $type);
844 574         1086 @nodes = ();
845 574 100 66     1736 if ($declared and defined $proto and not $amper) {
      66        
846 1         2 my $args;
847 1         12 ($amper, $args) = $self->check_proto($op, $proto, @exprs);
848 1 50       4 if ($amper eq "&") {
849 0         0 $self->deparse_op_siblings(\@nodes, $kid_start, $op, 6);
850             } else {
851 1 50       5 @nodes = @$args if @$args;
852             }
853             } else {
854 573         2657 $self->deparse_op_siblings(\@nodes, $kid_start, $op, 6);
855 573         2375 @nodes = map($self->deparse($_, 6, $op), @exprs);
856             }
857              
858 574 50 33     2735 if ($prefix or $amper) {
859 0 0       0 if ($sub_name eq '&') {
860             # &{&} cannot be written as &&
861 0         0 $subname_info->{texts} = ["{", @{$subname_info->{texts}}, "}"];
  0         0  
862 0         0 $subname_info->{text} = join('', $subname_info->{texts});
863             }
864 0 0       0 if ($op->flags & OPf_STACKED) {
865 0         0 $type = "$prefix$amper call()";
866 0         0 @texts = ($prefix, $amper, $subname_info, "(", $self->combine2str(', ', \@nodes), ")");
867             } else {
868 0         0 $type = "$prefix$amper call";
869 0         0 @texts = ($prefix, $amper, $subname_info);
870             }
871             } else {
872             # It's a syntax error to call CORE::GLOBAL::foo with a prefix,
873             # so it must have been translated from a keyword call. Translate
874             # it back.
875 574         1512 $subname_info->{text} =~ s/^CORE::GLOBAL:://;
876 574 100       1402 my $dproto = defined($proto) ? $proto : "undefined";
877 574 100 33     1200 if (!$declared) {
    50 33        
    50 33        
    50          
878 573         894 $type = 'call (fn without prototype)';
879 573         958 my ($fmt, $args_spec);
880 573 100       1669 my $first_param_text = (@nodes > 0) ? $nodes[0]->{text} : '';
881 573         1359 unshift @nodes, $subname_info;
882 573 50       2383 if ($self->dedup_func_parens(\@nodes)) {
883 0         0 $fmt = "%c %c";
884 0         0 $args_spec = undef;
885             } else {
886 573         972 $fmt = "%c(%C)";
887 573         1830 $args_spec = [0, [1, $#nodes, ', ']];
888             }
889 573         2640 my $node = $self->info_from_template($type, $op, $fmt, $args_spec,
890             \@nodes,
891             {other_ops => $other_ops});
892              
893              
894             # Take the subname_info portion of $node and use that as the
895             # part of the parent, null, pushmark ops.
896 573 50 33     2762 if ($subname_info && $other_ops) {
897 573         1259 my $str = $node->{text};
898 573         1747 my $position = [0, length($subname_info->{text})];
899 573         1167 my @new_ops = ();
900 573         1215 foreach my $skipped_op (@$other_ops) {
901 1146         6816 my $new_op = $self->info_from_string($op->name, $skipped_op, $str,
902             {position => $position});
903 1146         3106 push @new_ops, $new_op;
904             }
905 573         1547 $node->{other_ops} = \@new_ops;
906             }
907 573         2562 return $node;
908              
909             } elsif ($dproto =~ /^\s*\z/) {
910 0         0 $type = 'call no protype';
911 0         0 @texts = ($subname_info);
912             } elsif ($dproto eq "\$" and B::Deparse::is_scalar($exprs[0])) {
913 0         0 $type = 'call - $ prototype';
914             # is_scalar is an excessively conservative test here:
915             # really, we should be comparing to the precedence of the
916             # top operator of $exprs[0] (ala unop()), but that would
917             # take some major code restructuring to do right.
918 0         0 @texts = $self->maybe_parens_func($sub_name,
919             $self->combine2str(', ', \@nodes), $cx, 16);
920             } elsif ($dproto ne '$' and defined($proto) || $simple) { #'
921 1         5 $type = "call $sub_name having prototype";
922 1         7 @texts = $self->maybe_parens_func($sub_name,
923             $self->combine2str(', ', \@nodes), $cx, 5);
924 1         6 return B::DeparseTree::TreeNode->new($op, $self, \@texts,
925             '', $type,
926             {other_ops => $other_ops});
927             } else {
928 0         0 $type = 'call';
929 0         0 @texts = dedup_parens_func($self, $subname_info, \@nodes);
930 0         0 return B::DeparseTree::TreeNode->new($op, $self, \@texts,
931             '', $type,
932             {other_ops => $other_ops});
933             }
934             }
935 0         0 my $node = $self->info_from_template($type, $op,
936             '%C', [[0, $#texts, '']], \@texts,
937             {other_ops => $other_ops});
938              
939             # Take the subname_info portion of $node and use that as the
940             # part of the parent, null, pushmark ops.
941 0 0 0     0 if ($subname_info && $other_ops) {
942 0         0 my $str = $node->{text};
943 0         0 my $position = [0, length($subname_info->{text})];
944 0         0 my @new_ops = ();
945 0         0 foreach my $skipped_op (@$other_ops) {
946 0         0 my $new_op = $self->info_from_string($op->name, $skipped_op, $str,
947             {position => $position});
948 0         0 push @new_ops, $new_op;
949             }
950 0         0 $node->{other_ops} = \@new_ops;
951             }
952 0         0 return $node;
953             }
954              
955             sub pp_entereval {
956 12 100   12 0 89 unop(
957             @_,
958             $_[1]->private & OPpEVAL_BYTES ? 'evalbytes' : "eval"
959             )
960             }
961              
962             sub pp_flop
963             {
964 0     0 0 0 my $self = shift;
965 0         0 my($op, $cx) = @_;
966 0         0 my $flip = $op->first;
967 0 0       0 my $type = ($flip->flags & OPf_SPECIAL) ? "..." : "..";
968 0         0 my $node =$self->range($flip->first, $cx, $type);
969 0         0 return $self->info_from_template("pp_flop $type", $op, "%c", undef, [$node], {});
970             }
971              
972             sub pp_gv
973             {
974 1224     1224 0 2238 my($self, $op, $cx) = @_;
975 1224         10098 my $gv = $self->gv_or_padgv($op);
976 1224         22293 my $name = $self->gv_name($gv);
977 1224         5430 return $self->info_from_string("global variable $name", $op, $name);
978             }
979              
980             # FIXME: adjust use of maybe_local_str
981             sub pp_gvsv
982             {
983 1353     1353 0 2419 my($self, $op, $cx) = @_;
984 1353         11589 my $gv = $self->gv_or_padgv($op);
985 1353         26269 return $self->maybe_local_str($op, $cx,
986             $self->stash_variable("\$",
987             $self->gv_name($gv), $cx));
988             }
989              
990             sub pp_null
991             {
992 5255 50   5255 0 15772 $] < 5.022 ? null_older(@_) : null_newer(@_);
993             }
994              
995             sub pp_once
996             {
997 1     1 0 4 my ($self, $op, $cx) = @_;
998 1         8 my $cond = $op->first;
999 1         7 my $true = $cond->sibling;
1000              
1001 1         23 return $self->deparse($true, $cx);
1002             }
1003              
1004 45     45 0 180 sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
1005 0     0 0 0 sub pp_dor { logop(@_, "//", 10) }
1006              
1007 0     0 0 0 sub pp_mapwhile { mapop(@_, "map") }
1008 0     0 0 0 sub pp_grepwhile { mapop(@_, "grep") }
1009              
1010 5     5 0 33 sub pp_preinc { pfixop(@_, "++", 23) }
1011 0     0 0 0 sub pp_predec { pfixop(@_, "--", 23) }
1012 0     0 0 0 sub pp_i_preinc { pfixop(@_, "++", 23) }
1013 0     0 0 0 sub pp_i_predec { pfixop(@_, "--", 23) }
1014              
1015             sub pp_rcatline {
1016 0     0 0 0 my ($self, $op) = @_;
1017 0         0 return $self->info_from_string('rcatline <$fh>', $op,
1018             sprintf "<%s>", $self->gv_name($self->gv_or_padgv($op)));
1019             }
1020              
1021             sub pp_readline {
1022 6     6 0 21 my $self = shift;
1023 6         14 my($op, $cx) = @_;
1024 6         29 my $first_kid = $op->first;
1025 6         17 my $kid = $first_kid;
1026 6         20 my @other_ops;
1027             # Do we have <$fh>?
1028 6 50       32 if ($first_kid->name eq "rv2gv") {
1029 0         0 push @other_ops, $kid;
1030 0         0 $kid = $first_kid->first;
1031             }
1032 6 50 33     89 if (B::Deparse::is_scalar($kid) and
      66        
1033             ($] < 5.021 or
1034             ($op->flags & OPf_SPECIAL))) {
1035 0         0 my $kid_node = $self->deparse($kid, 1, $op);
1036 0 0       0 if ($kid_node->{text} eq 'ARGV') {
1037 0 0       0 if (@other_ops) {
1038             # skipped first node, also add $kid_node.
1039 0         0 push @other_ops, $kid_node;
1040             } else {
1041             # upgrade @other_ops from an op to a node
1042 0         0 @other_ops = ($kid_node);
1043             }
1044 0         0 return $self->info_from_string('readline <<>>', $op, '<<>>',
1045             {other_ops => [$first_kid, $kid_node]});
1046             } else {
1047 0         0 return $self->info_from_template('readline <$fh>', $op, "<%c>",
1048             undef, [$kid_node],
1049             {other_ops => @other_ops});
1050             }
1051             }
1052 6         32 my $node = $self->unop($op, $cx, "readline");
1053 6         15 push @{$node->{other_ops}}, $first_kid;
  6         17  
1054 6         18 return $node
1055             }
1056              
1057             sub pp_split {
1058             # 5.20 might drop "maybe_targmy?"
1059 0     0 0 0 maybe_targmy(@_, \&split, "split");
1060             }
1061              
1062             sub pp_stringify {
1063 0 0   0 0 0 $] < 5.022 ? stringify_older(@_) : stringify_newer(@_);
1064             }
1065              
1066             sub pp_subst {
1067 18 50   18 0 95 $] < 5.022 ? subst_older(@_) : subst_newer(@_);
1068             }
1069              
1070             # Perl 5.14 doesn't have this
1071 8     8   62 use constant OPpSUBSTR_REPL_FIRST => 16;
  8         16  
  8         4259  
1072              
1073             sub pp_substr {
1074 6     6 0 12 my ($self,$op,$cx) = @_;
1075 6 50       32 if ($op->private & OPpSUBSTR_REPL_FIRST) {
1076 0         0 my $left = listop($self, $op, 7, "substr", $op->first->sibling->sibling);
1077 0         0 my $right = $self->deparse($op->first->sibling, 7, $op);
1078 0         0 return info_from_list($op, $self,[$left, '=', $right], ' ',
1079             'substr_repl_first', {});
1080             }
1081 6         25 return maybe_local(@_, listop(@_, "substr"))
1082             }
1083              
1084             # FIXME:
1085             # Different between 5.20 and 5.22. We've used 5.22 though.
1086             # Go over and make sure this is okay.
1087             sub pp_stub {
1088 1286     1286 0 2975 my ($self, $op) = @_;
1089 1286         3402 $self->info_from_string('stub ()', $op, '()')
1090             };
1091              
1092             sub pp_trans {
1093 6     6 0 8 my $self = shift;
1094 6         9 my($op, $cx) = @_;
1095 6         7 my($from, $to);
1096 6         29 my $class = class($op);
1097 6         21 my $priv_flags = $op->private;
1098 6 50       12 if ($class eq "PVOP") {
    0          
1099 6         678 ($from, $to) = B::Deparse::tr_decode_byte($op->pv, $priv_flags);
1100             } elsif ($class eq "PADOP") {
1101 0         0 ($from, $to)
1102             = tr_decode_utf8($self->padval($op->padix)->RV, $priv_flags);
1103             } else { # class($op) eq "SVOP"
1104 0         0 ($from, $to) = B::Deparse::tr_decode_utf8($op->sv->RV, $priv_flags);
1105             }
1106 6         14 my $flags = "";
1107 6 100       14 $flags .= "c" if $priv_flags & OPpTRANS_COMPLEMENT;
1108 6 100       13 $flags .= "d" if $priv_flags & OPpTRANS_DELETE;
1109 6 100 66     26 $to = "" if $from eq $to and $flags eq "";
1110 6 100       14 $flags .= "s" if $priv_flags & OPpTRANS_SQUASH;
1111 6         83 return info_from_list($op, $self, ['tr', double_delim($from, $to), $flags],
1112             '', 'pp_trans', {});
1113             }
1114              
1115             sub pp_transr {
1116 2     2 0 5 my $self = $_[0];
1117 2         4 my $op = $_[1];
1118 2         6 my $info = pp_trans(@_);
1119             # FIXME: thrn into template as below
1120 2         16 return $self->info_from_string('pp_transr', $op, $info->{text} . 'r',
1121             {other_ops => [$info]});
1122             # return $self->info_from_template("trans r", "%cr", undef, [$info]);
1123             }
1124              
1125             sub pp_unstack {
1126 1     1 0 3 my ($self, $op) = @_;
1127             # see also leaveloop
1128 1         3 return $self->info_from_string("unstack", $op, '');
1129             }
1130              
1131             # xor is syntactically a logop, but it's really a binop (contrary to
1132             # old versions of opcode.pl). Syntax is what matters here.
1133 6     6 0 35 sub pp_xor { logop(@_, "xor", 2, "", 0, "") }
1134              
1135             1;