| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # B::DeparseTree::P526.pm | 
| 2 |  |  |  |  |  |  | # Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 Stephen McCamant. | 
| 3 |  |  |  |  |  |  | # Copyright (c) 2015, 2017, 2018 Rocky Bernstein | 
| 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 (for perl 5.22) 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 | 8 |  |  | 8 |  | 96 | use v5.26; | 
|  | 8 |  |  |  |  | 21 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 8 |  |  | 8 |  | 37 | use rlib '../..'; | 
|  | 8 |  |  |  |  | 14 |  | 
|  | 8 |  |  |  |  | 61 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | package B::DeparseTree::P526; | 
| 20 | 8 |  |  | 8 |  | 2510 | use Carp; | 
|  | 8 |  |  |  |  | 14 |  | 
|  | 8 |  |  |  |  | 803 |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 8 |  |  |  |  | 1595 | use B qw( | 
| 23 |  |  |  |  |  |  | CVf_METHOD | 
| 24 |  |  |  |  |  |  | MDEREF_ACTION_MASK | 
| 25 |  |  |  |  |  |  | MDEREF_AV_gvav_aelem | 
| 26 |  |  |  |  |  |  | MDEREF_AV_gvsv_vivify_rv2av_aelem | 
| 27 |  |  |  |  |  |  | MDEREF_AV_padav_aelem | 
| 28 |  |  |  |  |  |  | MDEREF_AV_padsv_vivify_rv2av_aelem | 
| 29 |  |  |  |  |  |  | MDEREF_AV_pop_rv2av_aelem | 
| 30 |  |  |  |  |  |  | MDEREF_AV_vivify_rv2av_aelem | 
| 31 |  |  |  |  |  |  | MDEREF_FLAG_last | 
| 32 |  |  |  |  |  |  | MDEREF_HV_gvhv_helem | 
| 33 |  |  |  |  |  |  | MDEREF_HV_gvsv_vivify_rv2hv_helem | 
| 34 |  |  |  |  |  |  | MDEREF_HV_padhv_helem | 
| 35 |  |  |  |  |  |  | MDEREF_HV_padsv_vivify_rv2hv_helem | 
| 36 |  |  |  |  |  |  | MDEREF_HV_pop_rv2hv_helem | 
| 37 |  |  |  |  |  |  | MDEREF_HV_vivify_rv2hv_helem | 
| 38 |  |  |  |  |  |  | MDEREF_INDEX_MASK | 
| 39 |  |  |  |  |  |  | MDEREF_INDEX_const | 
| 40 |  |  |  |  |  |  | MDEREF_INDEX_gvsv | 
| 41 |  |  |  |  |  |  | MDEREF_INDEX_none | 
| 42 |  |  |  |  |  |  | MDEREF_INDEX_padsv | 
| 43 |  |  |  |  |  |  | MDEREF_MASK | 
| 44 |  |  |  |  |  |  | MDEREF_SHIFT | 
| 45 |  |  |  |  |  |  | MDEREF_reload | 
| 46 |  |  |  |  |  |  | OPf_KIDS | 
| 47 |  |  |  |  |  |  | OPf_MOD | 
| 48 |  |  |  |  |  |  | OPf_PARENS | 
| 49 |  |  |  |  |  |  | OPf_REF | 
| 50 |  |  |  |  |  |  | OPf_SPECIAL | 
| 51 |  |  |  |  |  |  | OPf_STACKED | 
| 52 |  |  |  |  |  |  | OPf_WANT | 
| 53 |  |  |  |  |  |  | OPf_WANT_LIST | 
| 54 |  |  |  |  |  |  | OPf_WANT_SCALAR | 
| 55 |  |  |  |  |  |  | OPf_WANT_VOID | 
| 56 |  |  |  |  |  |  | OPpCONST_BARE | 
| 57 |  |  |  |  |  |  | OPpENTERSUB_AMPER | 
| 58 |  |  |  |  |  |  | OPpEXISTS_SUB | 
| 59 |  |  |  |  |  |  | OPpLVAL_INTRO | 
| 60 |  |  |  |  |  |  | OPpMULTIDEREF_DELETE | 
| 61 |  |  |  |  |  |  | OPpMULTIDEREF_EXISTS | 
| 62 |  |  |  |  |  |  | OPpOUR_INTRO | 
| 63 |  |  |  |  |  |  | OPpPADRANGE_COUNTSHIFT | 
| 64 |  |  |  |  |  |  | OPpSLICE | 
| 65 |  |  |  |  |  |  | OPpSORT_INTEGER | 
| 66 |  |  |  |  |  |  | OPpSORT_NUMERIC | 
| 67 |  |  |  |  |  |  | OPpSORT_REVERSE | 
| 68 |  |  |  |  |  |  | OPpSPLIT_ASSIGN OPpSPLIT_LEX | 
| 69 |  |  |  |  |  |  | OPpTARGET_MY | 
| 70 |  |  |  |  |  |  | PADNAMEt_OUTER | 
| 71 |  |  |  |  |  |  | PMf_CONTINUE | 
| 72 |  |  |  |  |  |  | PMf_EVAL | 
| 73 |  |  |  |  |  |  | PMf_EXTENDED | 
| 74 |  |  |  |  |  |  | PMf_EXTENDED_MORE | 
| 75 |  |  |  |  |  |  | PMf_FOLD | 
| 76 |  |  |  |  |  |  | PMf_GLOBAL | 
| 77 |  |  |  |  |  |  | PMf_KEEP | 
| 78 |  |  |  |  |  |  | PMf_MULTILINE | 
| 79 |  |  |  |  |  |  | PMf_ONCE | 
| 80 |  |  |  |  |  |  | PMf_SINGLELINE | 
| 81 |  |  |  |  |  |  | SVf_FAKE | 
| 82 |  |  |  |  |  |  | SVf_ROK SVpad_OUR | 
| 83 |  |  |  |  |  |  | SVpad_TYPED | 
| 84 |  |  |  |  |  |  | SVs_RMG | 
| 85 |  |  |  |  |  |  | SVs_SMG | 
| 86 |  |  |  |  |  |  | class | 
| 87 |  |  |  |  |  |  | main_cv | 
| 88 |  |  |  |  |  |  | main_root | 
| 89 |  |  |  |  |  |  | main_start | 
| 90 |  |  |  |  |  |  | opnumber | 
| 91 |  |  |  |  |  |  | perlstring | 
| 92 |  |  |  |  |  |  | svref_2object | 
| 93 | 8 |  |  | 8 |  | 43 | ); | 
|  | 8 |  |  |  |  | 13 |  | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 8 |  |  | 8 |  | 4498 | use B::DeparseTree::PPfns; | 
|  | 8 |  |  |  |  | 19 |  | 
|  | 8 |  |  |  |  | 2469 |  | 
| 96 | 8 |  |  | 8 |  | 63 | use B::DeparseTree::SyntaxTree; | 
|  | 8 |  |  |  |  | 13 |  | 
|  | 8 |  |  |  |  | 650 |  | 
| 97 | 8 |  |  | 8 |  | 3969 | use B::DeparseTree::PP; | 
|  | 8 |  |  |  |  | 18 |  | 
|  | 8 |  |  |  |  | 2490 |  | 
| 98 | 8 |  |  | 8 |  | 53 | use B::Deparse; | 
|  | 8 |  |  |  |  | 18 |  | 
|  | 8 |  |  |  |  | 1326 |  | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | # Copy unchanged functions from B::Deparse | 
| 101 |  |  |  |  |  |  | *begin_is_use = *B::Deparse::begin_is_use; | 
| 102 |  |  |  |  |  |  | *const_sv = *B::Deparse::const_sv; | 
| 103 |  |  |  |  |  |  | *escape_re = *B::Deparse::escape_re; | 
| 104 |  |  |  |  |  |  | *find_scope_st = *B::Deparse::find_scope_st; | 
| 105 |  |  |  |  |  |  | *gv_name = *B::Deparse::gv_name; | 
| 106 |  |  |  |  |  |  | *keyword = *B::Deparse::keyword; | 
| 107 |  |  |  |  |  |  | *meth_pad_subs = *B::Deparse::pad_subs; | 
| 108 |  |  |  |  |  |  | *meth_rclass_sv = *B::Deparse::meth_rclass_sv; | 
| 109 |  |  |  |  |  |  | *meth_sv = *B::Deparse::meth_sv; | 
| 110 |  |  |  |  |  |  | *padany = *B::Deparse::padany; | 
| 111 |  |  |  |  |  |  | *padname = *B::Deparse::padname; | 
| 112 |  |  |  |  |  |  | *padname_sv = *B::Deparse::padname_sv; | 
| 113 |  |  |  |  |  |  | *padval = *B::Deparse::padval; | 
| 114 |  |  |  |  |  |  | *re_flags = *B::Deparse::re_flags; | 
| 115 |  |  |  |  |  |  | *stash_variable = *B::Deparse::stash_variable; | 
| 116 |  |  |  |  |  |  | *stash_variable_name = *B::Deparse::stash_variable_name; | 
| 117 |  |  |  |  |  |  | *tr_chr = *B::Deparse::tr_chr; | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 8 |  |  | 8 |  | 48 | use strict; | 
|  | 8 |  |  |  |  | 14 |  | 
|  | 8 |  |  |  |  | 301 |  | 
| 120 | 8 |  |  | 8 |  | 42 | use vars qw/$AUTOLOAD/; | 
|  | 8 |  |  |  |  | 14 |  | 
|  | 8 |  |  |  |  | 327 |  | 
| 121 | 8 |  |  | 8 |  | 36 | use warnings (); | 
|  | 8 |  |  |  |  | 13 |  | 
|  | 8 |  |  |  |  | 837 |  | 
| 122 |  |  |  |  |  |  | require feature; | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | our(@EXPORT, @ISA); | 
| 125 |  |  |  |  |  |  | our $VERSION = '3.2.0'; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | @ISA = qw(B::DeparseTree::PP); | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | @EXPORT = qw(slice); | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | BEGIN { | 
| 132 |  |  |  |  |  |  | # List version-specific constants here. | 
| 133 |  |  |  |  |  |  | # Easiest way to keep this code portable between version looks to | 
| 134 |  |  |  |  |  |  | # be to fake up a dummy constant that will never actually be true. | 
| 135 | 8 |  |  | 8 |  | 37 | foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED OPpCONST_NOVER | 
| 136 |  |  |  |  |  |  | OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE | 
| 137 |  |  |  |  |  |  | PMf_CHARSET PMf_KEEPCOPY PMf_NOCAPTURE CVf_ANONCONST | 
| 138 |  |  |  |  |  |  | CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST | 
| 139 |  |  |  |  |  |  | PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES | 
| 140 |  |  |  |  |  |  | OPpLVREF_TYPE OPpLVREF_SV OPpLVREF_AV OPpLVREF_HV | 
| 141 |  |  |  |  |  |  | OPpLVREF_CV OPpLVREF_ELEM SVpad_STATE)) { | 
| 142 | 192 |  |  |  |  | 261 | eval { B->import($_) }; | 
|  | 192 |  |  |  |  | 8335 |  | 
| 143 | 8 |  |  | 8 |  | 48 | no strict 'refs'; | 
|  | 8 |  |  |  |  | 29 |  | 
|  | 8 |  |  |  |  | 560 |  | 
| 144 | 192 | 100 |  |  |  | 285 | *{$_} = sub () {0} unless *{$_}{CODE}; | 
|  | 24 |  |  |  |  | 89 |  | 
|  | 192 |  |  |  |  | 1408 |  | 
| 145 |  |  |  |  |  |  | } | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 8 |  |  | 8 |  | 27 | BEGIN { for (qw[ rv2sv aelem | 
| 149 |  |  |  |  |  |  | rv2av rv2hv helem custom ]) { | 
| 150 | 48 |  |  |  |  | 2566 | eval "sub OP_\U$_ () { " . opnumber($_) . "}" | 
| 151 |  |  |  |  |  |  | }} | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | # pp_padany -- does not exist after parsing | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 156 | 0 | 0 |  | 0 |  | 0 | if ($AUTOLOAD =~ s/^.*::pp_//) { | 
| 157 | 0 |  |  |  |  | 0 | warn "unexpected OP_".uc $AUTOLOAD; | 
| 158 | 0 | 0 |  |  |  | 0 | ($_[1]->type == OP_CUSTOM ? "CUSTOM ($AUTOLOAD)" : uc $AUTOLOAD); | 
| 159 | 0 |  |  |  |  | 0 | return "XXX"; | 
| 160 |  |  |  |  |  |  | } else { | 
| 161 | 0 |  |  |  |  | 0 | Carp::confess "Undefined subroutine $AUTOLOAD called"; | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  | 0 |  |  | sub DESTROY {}	#	Do not AUTOLOAD | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | # The BEGIN {} is used here because otherwise this code isn't executed | 
| 168 |  |  |  |  |  |  | # when you run B::Deparse on itself. | 
| 169 |  |  |  |  |  |  | my %globalnames; | 
| 170 | 8 |  |  | 8 |  | 266 | BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC", | 
| 171 |  |  |  |  |  |  | "ENV", "ARGV", "ARGVOUT", "_"); } | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 8 |  |  | 8 |  | 45 | { no strict 'refs'; *{"pp_r$_"} = *{"pp_$_"} for qw< keys each values >; } | 
|  | 8 |  |  |  |  | 13 |  | 
|  | 8 |  |  |  |  | 28381 |  | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | # FIXME: | 
| 176 |  |  |  |  |  |  | # Different in 5.20. Go over differences to see if okay in 5.20. | 
| 177 |  |  |  |  |  |  | sub pp_chdir { | 
| 178 | 0 |  |  | 0 | 0 | 0 | my ($self, $op, $cx) = @_; | 
| 179 | 0 | 0 |  |  |  | 0 | if (($op->flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS)) { | 
| 180 | 0 |  |  |  |  | 0 | my $kw = $self->keyword("chdir"); | 
| 181 | 0 |  |  |  |  | 0 | my $kid = $self->const_sv($op->first)->PV; | 
| 182 |  |  |  |  |  |  | my $code = $kw | 
| 183 | 0 | 0 | 0 |  |  | 0 | . ($cx >= 16 || $self->{'parens'} ? "($kid)" : " $kid"); | 
| 184 | 0 |  |  | 0 |  | 0 | maybe_targmy(@_, sub { $_[3] }, $code); | 
|  | 0 |  |  |  |  | 0 |  | 
| 185 |  |  |  |  |  |  | } else { | 
| 186 | 0 |  |  |  |  | 0 | maybe_targmy(@_, \&unop, "chdir") | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | my @threadsv_names = B::threadsv_names; | 
| 191 |  |  |  |  |  |  | sub pp_threadsv { | 
| 192 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 193 | 0 |  |  |  |  | 0 | my($op, $cx) = @_; | 
| 194 | 0 |  |  |  |  | 0 | return $self->maybe_local_str($op, $cx, "\$" .  $threadsv_names[$op->targ]); | 
| 195 |  |  |  |  |  |  | } | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 0 |  |  | 0 | 0 | 0 | sub pp_rv2sv { maybe_local_str(@_, rv2x(@_, "\$")) } | 
| 198 | 4 |  |  | 4 | 0 | 12 | sub pp_rv2hv { maybe_local_str(@_, rv2x(@_, "%")) } | 
| 199 | 6 |  |  | 6 | 0 | 19 | sub pp_rv2gv { maybe_local_str(@_, rv2x(@_, "*")) } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | # skip rv2av | 
| 202 |  |  |  |  |  |  | sub pp_av2arylen { | 
| 203 | 32 |  |  | 32 | 0 | 41 | my $self = shift; | 
| 204 | 32 |  |  |  |  | 50 | my($op, $cx) = @_; | 
| 205 | 32 | 50 |  |  |  | 118 | if ($op->first->name eq "padav") { | 
| 206 | 0 |  |  |  |  | 0 | return $self->maybe_local_str($op, $cx, '$#' . $self->padany($op->first)); | 
| 207 |  |  |  |  |  |  | } else { | 
| 208 | 32 |  |  |  |  | 121 | return $self->maybe_local_str($op, $cx, | 
| 209 |  |  |  |  |  |  | $self->rv2x($op->first, $cx, '$#')); | 
| 210 |  |  |  |  |  |  | } | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | sub pp_rv2av { | 
| 214 | 33 |  |  | 33 | 0 | 48 | my $self = shift; | 
| 215 | 33 |  |  |  |  | 61 | my($op, $cx) = @_; | 
| 216 | 33 |  |  |  |  | 101 | my $kid = $op->first; | 
| 217 | 33 | 50 |  |  |  | 127 | if ($kid->name eq "const") { # constant list | 
| 218 | 0 |  |  |  |  | 0 | my $av = $self->const_sv($kid); | 
| 219 | 0 |  |  |  |  | 0 | return $self->list_const($kid, $cx, $av->ARRAY); | 
| 220 |  |  |  |  |  |  | } else { | 
| 221 | 33 |  |  |  |  | 111 | return $self->maybe_local_str($op, $cx, | 
| 222 |  |  |  |  |  |  | $self->rv2x($op, $cx, "\@")); | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | sub elem_or_slice_array_name | 
| 227 |  |  |  |  |  |  | { | 
| 228 | 3 |  |  | 3 | 0 | 5 | my $self = shift; | 
| 229 | 3 |  |  |  |  | 8 | my ($array, $left, $padname, $allow_arrow) = @_; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 3 | 50 | 0 |  |  | 12 | if ($array->name eq $padname) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 232 | 3 |  |  |  |  | 38 | return $self->padany($array); | 
| 233 |  |  |  |  |  |  | } elsif (B::Deparse::is_scope($array)) { # ${expr}[0] | 
| 234 | 0 |  |  |  |  | 0 | return "{" . $self->deparse($array, 0) . "}"; | 
| 235 |  |  |  |  |  |  | } elsif ($array->name eq "gv") { | 
| 236 | 0 | 0 |  |  |  | 0 | ($array, my $quoted) = | 
| 237 |  |  |  |  |  |  | $self->stash_variable_name( | 
| 238 |  |  |  |  |  |  | $left eq '[' ? '@' : '%', $self->gv_or_padgv($array) | 
| 239 |  |  |  |  |  |  | ); | 
| 240 | 0 | 0 | 0 |  |  | 0 | if (!$allow_arrow && $quoted) { | 
| 241 |  |  |  |  |  |  | # This cannot happen. | 
| 242 | 0 |  |  |  |  | 0 | die "Invalid variable name $array for slice"; | 
| 243 |  |  |  |  |  |  | } | 
| 244 | 0 | 0 |  |  |  | 0 | return $quoted ? "$array->" : $array; | 
| 245 |  |  |  |  |  |  | } elsif (!$allow_arrow || B::Deparse::is_scalar $array) { | 
| 246 |  |  |  |  |  |  | # $x[0], $$x[0], ... | 
| 247 | 0 |  |  |  |  | 0 | return $self->deparse($array, 24)->{text}; | 
| 248 |  |  |  |  |  |  | } else { | 
| 249 | 0 |  |  |  |  | 0 | return undef; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | sub elem_or_slice_single_index($$) | 
| 254 |  |  |  |  |  |  | { | 
| 255 | 3 |  |  | 3 | 0 | 7 | my ($self, $idx, $parent) = @_; | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 3 |  |  |  |  | 11 | my $idx_info = $self->deparse($idx, 1, $parent); | 
| 258 | 3 |  |  |  |  | 7 | my $idx_str = $idx_info->{text}; | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | # Outer parens in an array index will confuse perl | 
| 261 |  |  |  |  |  |  | # if we're interpolating in a regular expression, i.e. | 
| 262 |  |  |  |  |  |  | # /$x$foo[(-1)]/ is *not* the same as /$x$foo[-1]/ | 
| 263 |  |  |  |  |  |  | # | 
| 264 |  |  |  |  |  |  | # If $self->{parens}, then an initial '(' will | 
| 265 |  |  |  |  |  |  | # definitely be paired with a final ')'. If | 
| 266 |  |  |  |  |  |  | # !$self->{parens}, the misleading parens won't | 
| 267 |  |  |  |  |  |  | # have been added in the first place. | 
| 268 |  |  |  |  |  |  | # | 
| 269 |  |  |  |  |  |  | # [You might think that we could get "(...)...(...)" | 
| 270 |  |  |  |  |  |  | # where the initial and final parens do not match | 
| 271 |  |  |  |  |  |  | # each other. But we can't, because the above would | 
| 272 |  |  |  |  |  |  | # only happen if there's an infix binop between the | 
| 273 |  |  |  |  |  |  | # two pairs of parens, and *that* means that the whole | 
| 274 |  |  |  |  |  |  | # expression would be parenthesized as well.] | 
| 275 |  |  |  |  |  |  | # | 
| 276 | 3 | 50 |  |  |  | 6 | $idx_str =~ s/^\((.*)\)$/$1/ if $self->{'parens'}; | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | # Hash-element braces will autoquote a bareword inside themselves. | 
| 279 |  |  |  |  |  |  | # We need to make sure that C<$hash{warn()}> doesn't come out as | 
| 280 |  |  |  |  |  |  | # C<$hash{warn}>, which has a quite different meaning. Currently | 
| 281 |  |  |  |  |  |  | # B::Deparse will always quote strings, even if the string was a | 
| 282 |  |  |  |  |  |  | # bareword in the original (i.e. the OPpCONST_BARE flag is ignored | 
| 283 |  |  |  |  |  |  | # for constant strings.) So we can cheat slightly here - if we see | 
| 284 |  |  |  |  |  |  | # a bareword, we know that it is supposed to be a function call. | 
| 285 |  |  |  |  |  |  | # | 
| 286 | 3 |  |  |  |  | 24 | $idx_str =~ s/^([A-Za-z_]\w*)$/$1()/; | 
| 287 |  |  |  |  |  |  |  | 
| 288 | 3 |  |  |  |  | 16 | return info_from_text($idx_info->{op}, $self, $idx_str, | 
| 289 |  |  |  |  |  |  | 'elem_or_slice_single_index', | 
| 290 |  |  |  |  |  |  | {body => [$idx_info]}); | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | sub elem | 
| 294 |  |  |  |  |  |  | { | 
| 295 | 0 |  |  | 0 |  | 0 | my ($self, $op, $cx, $left, $right, $padname) = @_; | 
| 296 | 0 |  |  |  |  | 0 | my($array, $idx) = ($op->first, $op->first->sibling); | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 0 |  |  |  |  | 0 | my $idx_info = $self->elem_or_slice_single_index($idx, $op); | 
| 299 | 0 |  |  |  |  | 0 | my $opts = {body => [$idx_info]}; | 
| 300 |  |  |  |  |  |  |  | 
| 301 | 0 | 0 |  |  |  | 0 | unless ($array->name eq $padname) { # Maybe this has been fixed | 
| 302 | 0 |  |  |  |  | 0 | $opts->{other_ops} = [$array]; | 
| 303 | 0 |  |  |  |  | 0 | $array = $array->first; # skip rv2av (or ex-rv2av in _53+) | 
| 304 |  |  |  |  |  |  | } | 
| 305 | 0 |  |  |  |  | 0 | my @texts = (); | 
| 306 | 0 |  |  |  |  | 0 | my $info; | 
| 307 | 0 |  |  |  |  | 0 | my $array_name=$self->elem_or_slice_array_name($array, $left, $padname, 1); | 
| 308 | 0 | 0 |  |  |  | 0 | if ($array_name) { | 
| 309 | 0 | 0 |  |  |  | 0 | if ($array_name !~ /->\z/) { | 
| 310 | 0 | 0 |  |  |  | 0 | if ($array_name eq '#') { | 
| 311 | 0 |  |  |  |  | 0 | $array_name = '${#}'; | 
| 312 |  |  |  |  |  |  | }  else { | 
| 313 | 0 |  |  |  |  | 0 | $array_name = '$' . $array_name ; | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  | } | 
| 316 | 0 |  |  |  |  | 0 | push @texts, $array_name; | 
| 317 | 0 | 0 |  |  |  | 0 | push @texts, $left if $left; | 
| 318 | 0 |  |  |  |  | 0 | push @texts, $idx_info->{text}, $right; | 
| 319 | 0 |  |  |  |  | 0 | return info_from_list($op, $self, \@texts, '', 'elem', $opts) | 
| 320 |  |  |  |  |  |  | } else { | 
| 321 |  |  |  |  |  |  | # $x[20][3]{hi} or expr->[20] | 
| 322 | 0 |  |  |  |  | 0 | my $type; | 
| 323 | 0 |  |  |  |  | 0 | my $array_info = $self->deparse($array, 24, $op); | 
| 324 | 0 |  |  |  |  | 0 | push @{$info->{body}}, $array_info; | 
|  | 0 |  |  |  |  | 0 |  | 
| 325 | 0 |  |  |  |  | 0 | @texts = ($array_info->{text}); | 
| 326 | 0 | 0 |  |  |  | 0 | if (B::Deparse::is_subscriptable($array)) { | 
| 327 | 0 |  |  |  |  | 0 | push @texts, $left, $idx_info->{text}, $right; | 
| 328 | 0 |  |  |  |  | 0 | $type = 'elem_no_arrow'; | 
| 329 |  |  |  |  |  |  | } else { | 
| 330 | 0 |  |  |  |  | 0 | push @texts, '->', $left, $idx_info->{text}, $right; | 
| 331 | 0 |  |  |  |  | 0 | $type = 'elem_arrow'; | 
| 332 |  |  |  |  |  |  | } | 
| 333 | 0 |  |  |  |  | 0 | return info_from_list($op, $self, \@texts, '', $type, $opts); | 
| 334 |  |  |  |  |  |  | } | 
| 335 | 0 |  |  |  |  | 0 | Carp::confess("unhandled condition in elem"); | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | # a simplified version of elem_or_slice_array_name() | 
| 339 |  |  |  |  |  |  | # for the use of pp_multideref | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | sub multideref_var_name($$$) | 
| 342 |  |  |  |  |  |  | { | 
| 343 | 7 |  |  | 7 | 0 | 13 | my ($self, $gv, $is_hash) = @_; | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 7 | 100 |  |  |  | 120 | my ($name, $quoted) = | 
| 346 |  |  |  |  |  |  | $self->stash_variable_name( $is_hash  ? '%' : '@', $gv); | 
| 347 | 7 | 100 |  |  |  | 31 | return $quoted ? "$name->" | 
|  |  | 50 |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | : $name eq '#' | 
| 349 |  |  |  |  |  |  | ? '${#}'       # avoid ${#}[1] => $#[1] | 
| 350 |  |  |  |  |  |  | : '$' . $name; | 
| 351 |  |  |  |  |  |  | } | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | sub pp_multideref | 
| 354 |  |  |  |  |  |  | { | 
| 355 | 9 |  |  | 9 | 0 | 20 | my($self, $op, $cx) = @_; | 
| 356 | 9 |  |  |  |  | 17 | my @texts = (); | 
| 357 |  |  |  |  |  |  |  | 
| 358 | 9 | 100 |  |  |  | 55 | if ($op->private & OPpMULTIDEREF_EXISTS) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 359 | 4 |  |  |  |  | 62 | @texts = ($self->keyword("exists"), ' '); | 
| 360 |  |  |  |  |  |  | } | 
| 361 |  |  |  |  |  |  | elsif ($op->private & OPpMULTIDEREF_DELETE) { | 
| 362 | 4 |  |  |  |  | 64 | @texts = ($self->keyword("delete"), ' ') | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  | elsif ($op->private & OPpLVAL_INTRO) { | 
| 365 | 0 |  |  |  |  | 0 | @texts = ($self->keyword("local"), ' ') | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  |  | 
| 368 | 9 | 50 | 33 |  |  | 80 | if ($op->first && ($op->first->flags & OPf_KIDS)) { | 
| 369 |  |  |  |  |  |  | # arbitrary initial expression, e.g. f(1,2,3)->[...] | 
| 370 | 0 |  |  |  |  | 0 | my $first = $self->deparse($op->first, 24, $op); | 
| 371 | 0 |  |  |  |  | 0 | push @texts, $first->{text}; | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  |  | 
| 374 | 9 |  |  |  |  | 55 | my @items = $op->aux_list($self->{curcv}); | 
| 375 | 9 |  |  |  |  | 17 | my $actions = shift @items; | 
| 376 |  |  |  |  |  |  |  | 
| 377 | 9 |  |  |  |  | 16 | my $is_hash; | 
| 378 | 9 |  |  |  |  | 11 | my $derefs = 0; | 
| 379 |  |  |  |  |  |  |  | 
| 380 | 9 |  |  |  |  | 12 | while (1) { | 
| 381 | 9 | 50 |  |  |  | 23 | if (($actions & MDEREF_ACTION_MASK) == MDEREF_reload) { | 
| 382 | 0 |  |  |  |  | 0 | $actions = shift @items; | 
| 383 | 0 |  |  |  |  | 0 | next; | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | $is_hash = ( | 
| 387 | 9 |  | 66 |  |  | 104 | ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_pop_rv2hv_helem | 
| 388 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvsv_vivify_rv2hv_helem | 
| 389 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padsv_vivify_rv2hv_helem | 
| 390 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_vivify_rv2hv_helem | 
| 391 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem | 
| 392 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem | 
| 393 |  |  |  |  |  |  | ); | 
| 394 |  |  |  |  |  |  |  | 
| 395 | 9 | 100 | 66 |  |  | 50 | if (   ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_padav_aelem | 
|  |  | 50 | 66 |  |  |  |  | 
| 396 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem) | 
| 397 |  |  |  |  |  |  | { | 
| 398 | 2 |  |  |  |  | 4 | $derefs = 1; | 
| 399 | 2 |  |  |  |  | 18 | push @texts, '$' . substr($self->padname(shift @items), 1); | 
| 400 |  |  |  |  |  |  | } | 
| 401 |  |  |  |  |  |  | elsif (   ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_gvav_aelem | 
| 402 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem) | 
| 403 |  |  |  |  |  |  | { | 
| 404 | 7 |  |  |  |  | 12 | $derefs = 1; | 
| 405 | 7 |  |  |  |  | 27 | push @texts, $self->multideref_var_name(shift @items, $is_hash); | 
| 406 |  |  |  |  |  |  | } | 
| 407 |  |  |  |  |  |  | else { | 
| 408 | 0 | 0 | 0 |  |  | 0 | if (   ($actions & MDEREF_ACTION_MASK) == | 
|  |  | 0 | 0 |  |  |  |  | 
|  |  | 0 | 0 |  |  |  |  | 
| 409 |  |  |  |  |  |  | MDEREF_AV_padsv_vivify_rv2av_aelem | 
| 410 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == | 
| 411 |  |  |  |  |  |  | MDEREF_HV_padsv_vivify_rv2hv_helem) | 
| 412 |  |  |  |  |  |  | { | 
| 413 | 0 |  |  |  |  | 0 | push @texts, $self->padname(shift @items); | 
| 414 |  |  |  |  |  |  | } | 
| 415 |  |  |  |  |  |  | elsif (   ($actions & MDEREF_ACTION_MASK) == | 
| 416 |  |  |  |  |  |  | MDEREF_AV_gvsv_vivify_rv2av_aelem | 
| 417 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == | 
| 418 |  |  |  |  |  |  | MDEREF_HV_gvsv_vivify_rv2hv_helem) | 
| 419 |  |  |  |  |  |  | { | 
| 420 | 0 |  |  |  |  | 0 | push @texts, $self->multideref_var_name(shift @items, $is_hash); | 
| 421 |  |  |  |  |  |  | } | 
| 422 |  |  |  |  |  |  | elsif (   ($actions & MDEREF_ACTION_MASK) == | 
| 423 |  |  |  |  |  |  | MDEREF_AV_pop_rv2av_aelem | 
| 424 |  |  |  |  |  |  | || ($actions & MDEREF_ACTION_MASK) == | 
| 425 |  |  |  |  |  |  | MDEREF_HV_pop_rv2hv_helem) | 
| 426 |  |  |  |  |  |  | { | 
| 427 | 0 | 0 | 0 |  |  | 0 | if (   ($op->flags & OPf_KIDS) | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 428 |  |  |  |  |  |  | && (   B::Deparse::_op_is_or_was($op->first, OP_RV2AV) | 
| 429 |  |  |  |  |  |  | || B::Deparse::_op_is_or_was($op->first, OP_RV2HV)) | 
| 430 |  |  |  |  |  |  | && ($op->first->flags & OPf_KIDS) | 
| 431 |  |  |  |  |  |  | && (   B::Deparse::_op_is_or_was($op->first->first, OP_AELEM) | 
| 432 |  |  |  |  |  |  | || B::Deparse::_op_is_or_was($op->first->first, OP_HELEM)) | 
| 433 |  |  |  |  |  |  | ) | 
| 434 |  |  |  |  |  |  | { | 
| 435 | 0 |  |  |  |  | 0 | $derefs++; | 
| 436 |  |  |  |  |  |  | } | 
| 437 |  |  |  |  |  |  | } | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 0 | 0 |  |  |  | 0 | push(@texts, '->') if !$derefs++; | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  |  | 
| 443 | 9 | 50 |  |  |  | 30 | if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_none) { | 
| 444 | 0 |  |  |  |  | 0 | last; | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  |  | 
| 447 | 9 | 100 |  |  |  | 33 | push(@texts, $is_hash ? '{' : '['); | 
| 448 |  |  |  |  |  |  |  | 
| 449 | 9 | 50 |  |  |  | 19 | if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_const) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 450 | 9 |  |  |  |  | 13 | my $key = shift @items; | 
| 451 | 9 | 100 |  |  |  | 16 | if ($is_hash) { | 
| 452 | 5 |  |  |  |  | 19 | push @texts, $self->const($key, $cx)->{text}; | 
| 453 |  |  |  |  |  |  | } | 
| 454 |  |  |  |  |  |  | else { | 
| 455 | 4 |  |  |  |  | 8 | push @texts, $key; | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  | } | 
| 458 |  |  |  |  |  |  | elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_padsv) { | 
| 459 | 0 |  |  |  |  | 0 | push @texts, $self->padname(shift @items); | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  | elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_gvsv) { | 
| 462 | 0 |  |  |  |  | 0 | push @texts,('$' .  ($self->stash_variable_name('$', shift @items))[0]); | 
| 463 |  |  |  |  |  |  | } | 
| 464 |  |  |  |  |  |  |  | 
| 465 | 9 | 100 |  |  |  | 39 | push(@texts, $is_hash ? '}' : ']'); | 
| 466 |  |  |  |  |  |  |  | 
| 467 | 9 | 50 |  |  |  | 22 | if ($actions & MDEREF_FLAG_last) { | 
| 468 | 9 |  |  |  |  | 21 | last; | 
| 469 |  |  |  |  |  |  | } | 
| 470 | 0 |  |  |  |  | 0 | $actions >>= MDEREF_SHIFT; | 
| 471 |  |  |  |  |  |  | } | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 9 |  |  |  |  | 32 | return info_from_list($op, $self, \@texts, '', 'multideref', {}); | 
| 474 |  |  |  |  |  |  | } | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  | # returns "&"  and the argument bodies if the prototype doesn't match the args, | 
| 477 |  |  |  |  |  |  | # or ("", $args_after_prototype_demunging) if it does. | 
| 478 |  |  |  |  |  |  | sub check_proto { | 
| 479 | 1 |  |  | 1 | 0 | 3 | my $self = shift; | 
| 480 | 1 |  |  |  |  | 2 | my $op = shift; | 
| 481 | 1 | 50 |  |  |  | 4 | return ('&', []) if $self->{'noproto'}; | 
| 482 | 1 |  |  |  |  | 4 | my($proto, @args) = @_; | 
| 483 | 1 |  |  |  |  | 2 | my($arg, $real); | 
| 484 | 1 |  |  |  |  | 2 | my $doneok = 0; | 
| 485 | 1 |  |  |  |  | 2 | my @reals; | 
| 486 |  |  |  |  |  |  | # An unbackslashed @ or % gobbles up the rest of the args | 
| 487 | 1 |  |  |  |  | 4 | 1 while $proto =~ s/(? | 
| 488 | 1 |  |  |  |  | 4 | $proto =~ s/^\s*//; | 
| 489 | 1 |  |  |  |  | 4 | while ($proto) { | 
| 490 | 4 |  |  |  |  | 14 | $proto =~ s/^(\\?[\$\@&%*_]|\\\[[\$\@&%*]+\]|;)\s*//; | 
| 491 | 4 |  |  |  |  | 9 | my $chr = $1; | 
| 492 | 4 | 50 | 33 |  |  | 26 | if ($chr eq "") { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 493 | 0 | 0 |  |  |  | 0 | return ('&', []) if @args; | 
| 494 |  |  |  |  |  |  | } elsif ($chr eq ";") { | 
| 495 | 1 |  |  |  |  | 3 | $doneok = 1; | 
| 496 |  |  |  |  |  |  | } elsif ($chr eq "@" or $chr eq "%") { | 
| 497 | 0 |  |  |  |  | 0 | push @reals, map($self->deparse($_, 6), @args, $op); | 
| 498 | 0 |  |  |  |  | 0 | @args = (); | 
| 499 |  |  |  |  |  |  | } else { | 
| 500 | 3 |  |  |  |  | 4 | $arg = shift @args; | 
| 501 | 3 | 100 |  |  |  | 8 | last unless $arg; | 
| 502 | 2 | 50 | 33 |  |  | 6 | if ($chr eq "\$" || $chr eq "_") { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 503 | 2 | 50 |  |  |  | 12 | if (B::Deparse::want_scalar $arg) { | 
| 504 | 2 |  |  |  |  | 6 | push @reals, $self->deparse($arg, 6, $op); | 
| 505 |  |  |  |  |  |  | } else { | 
| 506 | 0 |  |  |  |  | 0 | return ('&', []); | 
| 507 |  |  |  |  |  |  | } | 
| 508 |  |  |  |  |  |  | } elsif ($chr eq "&") { | 
| 509 | 0 | 0 |  |  |  | 0 | if ($arg->name =~ /^(s?refgen|undef)$/) { | 
| 510 | 0 |  |  |  |  | 0 | push @reals, $self->deparse($arg, 6, $op); | 
| 511 |  |  |  |  |  |  | } else { | 
| 512 | 0 |  |  |  |  | 0 | return ('&', []); | 
| 513 |  |  |  |  |  |  | } | 
| 514 |  |  |  |  |  |  | } elsif ($chr eq "*") { | 
| 515 | 0 | 0 | 0 |  |  | 0 | if ($arg->name =~ /^s?refgen$/ | 
| 516 |  |  |  |  |  |  | and $arg->first->first->name eq "rv2gv") | 
| 517 |  |  |  |  |  |  | { | 
| 518 | 0 |  |  |  |  | 0 | $real = $arg->first->first; # skip refgen, null | 
| 519 | 0 | 0 |  |  |  | 0 | if ($real->first->name eq "gv") { | 
| 520 | 0 |  |  |  |  | 0 | push @reals, $self->deparse($real, 6, $op); | 
| 521 |  |  |  |  |  |  | } else { | 
| 522 | 0 |  |  |  |  | 0 | push @reals, $self->deparse($real->first, 6, $op); | 
| 523 |  |  |  |  |  |  | } | 
| 524 |  |  |  |  |  |  | } else { | 
| 525 | 0 |  |  |  |  | 0 | return ('&', []); | 
| 526 |  |  |  |  |  |  | } | 
| 527 |  |  |  |  |  |  | } elsif (substr($chr, 0, 1) eq "\\") { | 
| 528 | 0 |  |  |  |  | 0 | $chr =~ tr/\\[]//d; | 
| 529 | 0 | 0 | 0 |  |  | 0 | if ($arg->name =~ /^s?refgen$/ and | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 530 |  |  |  |  |  |  | !B::Deparse::null($real = $arg->first) and | 
| 531 |  |  |  |  |  |  | ($chr =~ /\$/ && B::Deparse::is_scalar($real->first) | 
| 532 |  |  |  |  |  |  | or ($chr =~ /@/ | 
| 533 |  |  |  |  |  |  | && class($real->first->sibling) ne 'NULL' | 
| 534 |  |  |  |  |  |  | && $real->first->sibling->name | 
| 535 |  |  |  |  |  |  | =~ /^(rv2|pad)av$/) | 
| 536 |  |  |  |  |  |  | or ($chr =~ /%/ | 
| 537 |  |  |  |  |  |  | && class($real->first->sibling) ne 'NULL' | 
| 538 |  |  |  |  |  |  | && $real->first->sibling->name | 
| 539 |  |  |  |  |  |  | =~ /^(rv2|pad)hv$/) | 
| 540 |  |  |  |  |  |  | #or ($chr =~ /&/ # This doesn't work | 
| 541 |  |  |  |  |  |  | #   && $real->first->name eq "rv2cv") | 
| 542 |  |  |  |  |  |  | or ($chr =~ /\*/ | 
| 543 |  |  |  |  |  |  | && $real->first->name eq "rv2gv"))) | 
| 544 |  |  |  |  |  |  | { | 
| 545 | 0 |  |  |  |  | 0 | push @reals, $self->deparse($real, 6, $op); | 
| 546 |  |  |  |  |  |  | } else { | 
| 547 | 0 |  |  |  |  | 0 | return ('&', []); | 
| 548 |  |  |  |  |  |  | } | 
| 549 |  |  |  |  |  |  | } | 
| 550 |  |  |  |  |  |  | } | 
| 551 |  |  |  |  |  |  | } | 
| 552 | 1 | 50 | 33 |  |  | 4 | return ('&', []) if $proto and !$doneok; # too few args and no ';' | 
| 553 | 1 | 50 |  |  |  | 3 | return ('&', []) if @args;               # too many args | 
| 554 | 1 |  |  |  |  | 12 | return ('', \@reals); | 
| 555 |  |  |  |  |  |  | } | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | # Like dq(), but different | 
| 558 |  |  |  |  |  |  | sub re_dq { | 
| 559 | 1 |  |  | 1 | 0 | 3 | my $self = shift; | 
| 560 | 1 |  |  |  |  | 2 | my ($op) = @_; | 
| 561 | 1 |  |  |  |  | 2 | my ($re_dq_info, $fmt); | 
| 562 |  |  |  |  |  |  |  | 
| 563 | 1 |  |  |  |  | 4 | my $type = $op->name; | 
| 564 | 1 | 50 |  |  |  | 14 | if ($type eq "const") { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 565 | 0 | 0 |  |  |  | 0 | return '$[' if $op->private & OPpCONST_ARYBASE; | 
| 566 | 0 |  |  |  |  | 0 | my $unbacked = B::Deparse::re_unback($self->const_sv($op)->as_string); | 
| 567 | 0 |  |  |  |  | 0 | return B::Deparse::re_uninterp(escape_re($unbacked)); | 
| 568 |  |  |  |  |  |  | } elsif ($type eq "concat") { | 
| 569 | 0 |  |  |  |  | 0 | my $first = $self->re_dq($op->first); | 
| 570 | 0 |  |  |  |  | 0 | my $last  = $self->re_dq($op->last); | 
| 571 | 0 |  |  |  |  | 0 | return B::Deparse::re_dq_disambiguate($first, $last); | 
| 572 |  |  |  |  |  |  | } elsif ($type eq "uc") { | 
| 573 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 574 | 0 |  |  |  |  | 0 | $fmt = '\U%c\E'; | 
| 575 | 0 |  |  |  |  | 0 | $type .= ' uc'; | 
| 576 |  |  |  |  |  |  | } elsif ($type eq "lc") { | 
| 577 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 578 | 0 |  |  |  |  | 0 | $fmt = '\L%c\E'; | 
| 579 | 0 |  |  |  |  | 0 | $type .= ' lc'; | 
| 580 |  |  |  |  |  |  | } elsif ($type eq "ucfirst") { | 
| 581 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 582 | 0 |  |  |  |  | 0 | $fmt = '\u%c'; | 
| 583 | 0 |  |  |  |  | 0 | $type .= ' ucfirst'; | 
| 584 |  |  |  |  |  |  | } elsif ($type eq "lcfirst") { | 
| 585 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 586 | 0 |  |  |  |  | 0 | $fmt = '\u%c'; | 
| 587 | 0 |  |  |  |  | 0 | $type .= ' lcfirst'; | 
| 588 |  |  |  |  |  |  | } elsif ($type eq "quotemeta") { | 
| 589 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 590 | 0 |  |  |  |  | 0 | $fmt = '\Q%c\E'; | 
| 591 | 0 |  |  |  |  | 0 | $type .= ' quotemeta'; | 
| 592 |  |  |  |  |  |  | } elsif ($type eq "fc") { | 
| 593 | 0 |  |  |  |  | 0 | $re_dq_info = $self->re_dq($op->first->sibling); | 
| 594 | 0 |  |  |  |  | 0 | $fmt = '\F%c\E'; | 
| 595 | 0 |  |  |  |  | 0 | $type .= ' fc'; | 
| 596 |  |  |  |  |  |  | } elsif ($type eq "join") { | 
| 597 | 0 |  |  |  |  | 0 | return $self->deparse($op->last, 26); # was join($", @ary) | 
| 598 |  |  |  |  |  |  | } else { | 
| 599 | 1 |  |  |  |  | 5 | my $ret = $self->deparse($op, 26); | 
| 600 | 1 | 50 |  |  |  | 7 | $ret =~ s/^\$([(|)])\z/\${$1}/ # $( $| $) need braces | 
| 601 |  |  |  |  |  |  | or $ret =~ s/^\@([-+])\z/\@{$1}/; # @- @+ need braces | 
| 602 | 1 |  |  |  |  | 3 | return $ret; | 
| 603 |  |  |  |  |  |  | } | 
| 604 | 0 |  |  |  |  | 0 | return $self->info_from_template($type, $op->first->sibling, | 
| 605 |  |  |  |  |  |  | $fmt, [$re_dq_info], [0]); | 
| 606 |  |  |  |  |  |  | } | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | sub pure_string { | 
| 609 | 8 |  |  | 8 | 0 | 24 | my ($self, $op) = @_; | 
| 610 | 8 | 50 |  |  |  | 46 | return 0 if B::Deparse::null $op; | 
| 611 | 8 |  |  |  |  | 31 | my $type = $op->name; | 
| 612 |  |  |  |  |  |  |  | 
| 613 | 8 | 50 | 33 |  |  | 249 | if ($type eq 'const' || $type eq 'av2arylen') { | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  | 50 | 66 |  |  |  |  | 
|  |  | 50 | 66 |  |  |  |  | 
|  |  | 100 | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 614 | 0 |  |  |  |  | 0 | return 1; | 
| 615 |  |  |  |  |  |  | } | 
| 616 |  |  |  |  |  |  | elsif ($type =~ /^(?:[ul]c(first)?|fc)$/ || $type eq 'quotemeta') { | 
| 617 | 0 |  |  |  |  | 0 | return $self->pure_string($op->first->sibling); | 
| 618 |  |  |  |  |  |  | } | 
| 619 |  |  |  |  |  |  | elsif ($type eq 'join') { | 
| 620 | 0 |  |  |  |  | 0 | my $join_op = $op->first->sibling;  # Skip pushmark | 
| 621 | 0 | 0 | 0 |  |  | 0 | return 0 unless $join_op->name eq 'null' && $join_op->targ == OP_RV2SV; | 
| 622 |  |  |  |  |  |  |  | 
| 623 | 0 |  |  |  |  | 0 | my $gvop = $join_op->first; | 
| 624 | 0 | 0 |  |  |  | 0 | return 0 unless $gvop->name eq 'gvsv'; | 
| 625 | 0 | 0 |  |  |  | 0 | return 0 unless '"' eq $self->gv_name($self->gv_or_padgv($gvop)); | 
| 626 |  |  |  |  |  |  |  | 
| 627 | 0 | 0 |  |  |  | 0 | return 0 unless ${$join_op->sibling} eq ${$op->last}; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 628 | 0 | 0 |  |  |  | 0 | return 0 unless $op->last->name =~ /^(?:[ah]slice|(?:rv2|pad)av)$/; | 
| 629 |  |  |  |  |  |  | } | 
| 630 |  |  |  |  |  |  | elsif ($type eq 'concat') { | 
| 631 | 0 |  | 0 |  |  | 0 | return $self->pure_string($op->first) | 
| 632 |  |  |  |  |  |  | && $self->pure_string($op->last); | 
| 633 |  |  |  |  |  |  | } | 
| 634 |  |  |  |  |  |  | elsif (B::Deparse::is_scalar($op) || $type =~ /^[ah]elem$/) { | 
| 635 | 0 |  |  |  |  | 0 | return 1; | 
| 636 |  |  |  |  |  |  | } | 
| 637 |  |  |  |  |  |  | elsif ($type eq "null" and $op->can('first') and not B::Deparse::null $op->first and | 
| 638 |  |  |  |  |  |  | ($op->first->name eq "null" and $op->first->can('first') | 
| 639 |  |  |  |  |  |  | and not B::Deparse::null $op->first->first and | 
| 640 |  |  |  |  |  |  | $op->first->first->name eq "aelemfast" | 
| 641 |  |  |  |  |  |  | or | 
| 642 |  |  |  |  |  |  | $op->first->name =~ /^aelemfast(?:_lex)?\z/ | 
| 643 |  |  |  |  |  |  | )) { | 
| 644 | 1 |  |  |  |  | 6 | return 1; | 
| 645 |  |  |  |  |  |  | } | 
| 646 |  |  |  |  |  |  | else { | 
| 647 | 7 |  |  |  |  | 23 | return 0; | 
| 648 |  |  |  |  |  |  | } | 
| 649 |  |  |  |  |  |  |  | 
| 650 | 0 |  |  |  |  | 0 | return 1; | 
| 651 |  |  |  |  |  |  | } | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | sub regcomp | 
| 654 |  |  |  |  |  |  | { | 
| 655 | 5 |  |  | 5 | 0 | 12 | my($self, $op, $cx, $extended) = @_; | 
| 656 | 5 |  |  |  |  | 7 | my @other_ops = (); | 
| 657 | 5 |  |  |  |  | 15 | my $kid = $op->first; | 
| 658 | 5 | 50 |  |  |  | 19 | if ($kid->name eq "regcmaybe") { | 
| 659 | 0 |  |  |  |  | 0 | push @other_ops, $kid; | 
| 660 | 0 |  |  |  |  | 0 | $kid = $kid->first; | 
| 661 |  |  |  |  |  |  | } | 
| 662 | 5 | 50 |  |  |  | 15 | if ($kid->name eq "regcreset") { | 
| 663 | 0 |  |  |  |  | 0 | push @other_ops, $kid; | 
| 664 | 0 |  |  |  |  | 0 | $kid = $kid->first; | 
| 665 |  |  |  |  |  |  | } | 
| 666 | 5 | 50 | 66 |  |  | 35 | if ($kid->name eq "null" and !B::Deparse::null($kid->first) | 
|  |  |  | 66 |  |  |  |  | 
| 667 |  |  |  |  |  |  | and $kid->first->name eq 'pushmark') { | 
| 668 | 0 |  |  |  |  | 0 | my $str = ''; | 
| 669 | 0 |  |  |  |  | 0 | push(@other_ops, $kid); | 
| 670 | 0 |  |  |  |  | 0 | $kid = $kid->first->sibling; | 
| 671 | 0 |  |  |  |  | 0 | my @body = (); | 
| 672 | 0 |  |  |  |  | 0 | while (!B::Deparse::null($kid)) { | 
| 673 | 0 |  |  |  |  | 0 | my $first = $str; | 
| 674 | 0 |  |  |  |  | 0 | my $last = $self->re_dq($kid, $extended); | 
| 675 | 0 |  |  |  |  | 0 | push @body, $last; | 
| 676 | 0 |  |  |  |  | 0 | push(@other_ops, $kid); | 
| 677 | 0 |  |  |  |  | 0 | $str = B::Deparse::re_dq_disambiguate($first, | 
| 678 |  |  |  |  |  |  | $self->info2str($last)); | 
| 679 | 0 |  |  |  |  | 0 | $kid = $kid->sibling; | 
| 680 |  |  |  |  |  |  | } | 
| 681 | 0 |  |  |  |  | 0 | return (info_from_text($op, $self, $str, 'regcomp', | 
| 682 |  |  |  |  |  |  | {other_ops => \@other_ops, | 
| 683 |  |  |  |  |  |  | body => \@body}), 1); | 
| 684 |  |  |  |  |  |  | } | 
| 685 |  |  |  |  |  |  |  | 
| 686 | 5 | 100 |  |  |  | 16 | if ($self->pure_string($kid)) { | 
| 687 | 1 |  |  |  |  | 11 | my $info = $self->re_dq($kid, $extended); | 
| 688 | 1 | 50 |  |  |  | 4 | my @kid_ops = $info->{other_ops} ? @{$info->{other_ops}} : (); | 
|  | 0 |  |  |  |  | 0 |  | 
| 689 | 1 |  |  |  |  | 2 | push @other_ops, @kid_ops; | 
| 690 | 1 |  |  |  |  | 3 | $info->{other_ops} = \@other_ops; | 
| 691 | 1 |  |  |  |  | 4 | return ($info, 1); | 
| 692 |  |  |  |  |  |  | } | 
| 693 | 4 |  |  |  |  | 13 | return ($self->deparse($kid, $cx, $op), 0, $op); | 
| 694 |  |  |  |  |  |  | } | 
| 695 |  |  |  |  |  |  |  | 
| 696 |  |  |  |  |  |  | sub pp_split | 
| 697 |  |  |  |  |  |  | { | 
| 698 | 0 |  |  | 0 |  |  | my($self, $op, $cx) = @_; | 
| 699 | 0 |  |  |  |  |  | my($kid, @exprs, $ary_info, $expr); | 
| 700 | 0 |  |  |  |  |  | my $stacked = $op->flags & OPf_STACKED; | 
| 701 | 0 |  |  |  |  |  | my $ary = ''; | 
| 702 | 0 |  |  |  |  |  | my @body = (); | 
| 703 | 0 |  |  |  |  |  | my @other_ops = (); | 
| 704 | 0 |  |  |  |  |  | $kid = $op->first; | 
| 705 |  |  |  |  |  |  |  | 
| 706 | 0 |  |  |  |  |  | $kid = $op->first; | 
| 707 | 0 | 0 |  |  |  |  | $kid = $kid->sibling if $kid->name eq 'regcomp'; | 
| 708 | 0 |  |  |  |  |  | for (; !B::Deparse::null($kid); $kid = $kid->sibling) { | 
| 709 | 0 |  |  |  |  |  | push @exprs, $self->deparse($kid, 6, $op); | 
| 710 |  |  |  |  |  |  | } | 
| 711 |  |  |  |  |  |  |  | 
| 712 | 0 |  |  |  |  |  | unshift @exprs, $self->matchop($op, $cx, "m", "/"); | 
| 713 |  |  |  |  |  |  |  | 
| 714 | 0 | 0 |  |  |  |  | if ($op->private & OPpSPLIT_ASSIGN) { | 
| 715 |  |  |  |  |  |  | # With C<@array = split(/pat/, str);>, | 
| 716 |  |  |  |  |  |  | #  array is stored in split's pmreplroot; either | 
| 717 |  |  |  |  |  |  | # as an integer index into the pad (for a lexical array) | 
| 718 |  |  |  |  |  |  | # or as GV for a package array (which will be a pad index | 
| 719 |  |  |  |  |  |  | # on threaded builds) | 
| 720 |  |  |  |  |  |  | # With my/our @array = split(/pat/, str), the array is instead | 
| 721 |  |  |  |  |  |  | # accessed via an extra padav/rv2av op at the end of the | 
| 722 |  |  |  |  |  |  | # split's kid ops. | 
| 723 |  |  |  |  |  |  |  | 
| 724 | 0 | 0 |  |  |  |  | if ($stacked) { | 
| 725 | 0 |  |  |  |  |  | $ary = pop @exprs; | 
| 726 |  |  |  |  |  |  | } | 
| 727 |  |  |  |  |  |  | else { | 
| 728 | 0 | 0 |  |  |  |  | if ($op->private & OPpSPLIT_LEX) { | 
| 729 | 0 |  |  |  |  |  | $ary = $self->padname($op->pmreplroot); | 
| 730 |  |  |  |  |  |  | } | 
| 731 |  |  |  |  |  |  | else { | 
| 732 |  |  |  |  |  |  | # union with op_pmtargetoff, op_pmtargetgv | 
| 733 | 0 |  |  |  |  |  | my $gv = $op->pmreplroot; | 
| 734 | 0 | 0 |  |  |  |  | $gv = $self->padval($gv) if !ref($gv); | 
| 735 | 0 |  |  |  |  |  | $ary = $self->maybe_local(@_, | 
| 736 |  |  |  |  |  |  | $self->stash_variable('@', | 
| 737 |  |  |  |  |  |  | $self->gv_name($gv), | 
| 738 |  |  |  |  |  |  | $cx)) | 
| 739 |  |  |  |  |  |  | } | 
| 740 | 0 | 0 |  |  |  |  | if ($op->private & OPpLVAL_INTRO) { | 
| 741 | 0 | 0 |  |  |  |  | $ary = $op->private & OPpSPLIT_LEX ? "my $ary" : "local $ary"; | 
| 742 |  |  |  |  |  |  | } | 
| 743 |  |  |  |  |  |  | } | 
| 744 |  |  |  |  |  |  | } | 
| 745 |  |  |  |  |  |  |  | 
| 746 | 0 |  |  |  |  |  | push @body, @exprs; | 
| 747 | 0 |  |  |  |  |  | my $opts = {body => \@exprs}; | 
| 748 |  |  |  |  |  |  |  | 
| 749 |  |  |  |  |  |  | # handle special case of split(), and split(' ') that compiles to /\s+/ | 
| 750 | 0 | 0 | 0 |  |  |  | if (($op->reflags // 0) & RXf_SKIPWHITE()) { | 
| 751 | 0 |  |  |  |  |  | my $expr0 = $exprs[0]; | 
| 752 | 0 |  |  |  |  |  | my $expr0b0 = $expr0->{body}[0]; | 
| 753 | 0 |  |  |  |  |  | my $bsep = $expr0b0->{sep}; | 
| 754 | 0 |  |  |  |  |  | my $sep = $expr0->{sep}; | 
| 755 | 0 |  |  |  |  |  | $expr0b0->{texts}[1] = ' '; | 
| 756 |  |  |  |  |  |  | # substr($expr0b0->{text}, 1, 0) = ' '; | 
| 757 | 0 |  |  |  |  |  | substr($expr0->{texts}[0], 1, 0) = ' '; | 
| 758 | 0 |  |  |  |  |  | substr($expr0->{text}, 1, 0) = ' '; | 
| 759 |  |  |  |  |  |  | } | 
| 760 | 0 |  |  |  |  |  | my @args_texts = map $_->{text}, @exprs; | 
| 761 |  |  |  |  |  |  |  | 
| 762 | 0 |  |  |  |  |  | my $sep = ''; | 
| 763 | 0 |  |  |  |  |  | my $type; | 
| 764 |  |  |  |  |  |  | my @expr_texts; | 
| 765 | 0 | 0 |  |  |  |  | if ($ary) { | 
| 766 | 0 |  |  |  |  |  | @expr_texts = ("$ary", '=', join(', ', @args_texts)); | 
| 767 | 0 |  |  |  |  |  | $sep = ' '; | 
| 768 | 0 |  |  |  |  |  | $type = 'split_array'; | 
| 769 | 0 |  |  |  |  |  | $opts->{maybe_parens} = [$self, $cx, 7]; | 
| 770 |  |  |  |  |  |  | } else { | 
| 771 | 0 |  |  |  |  |  | @expr_texts = ('split', '(', join(', ', @args_texts), ')'); | 
| 772 | 0 |  |  |  |  |  | $type = 'split'; | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | } | 
| 775 | 0 |  |  |  |  |  | return info_from_list($op, $self, \@expr_texts, $sep, $type, $opts); | 
| 776 |  |  |  |  |  |  | } | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | # Not in Perl 5.20 and presumably < 5.20. No harm in adding to 5.20? | 
| 779 |  |  |  |  |  |  | *pp_ncomplement = *pp_complement; | 
| 780 |  |  |  |  |  |  |  | 
| 781 |  |  |  |  |  |  | 1; |