1 |
# B::Deparse.pm |
2 |
# Copyright (c) 1998, 1999, 2000 Stephen McCamant. All rights reserved. |
3 |
# This module is free software; you can redistribute and/or modify |
4 |
# it under the same terms as Perl itself. |
5 |
|
6 |
# This is based on the module of the same name by Malcolm Beattie, |
7 |
# but essentially none of his code remains. |
8 |
|
9 |
package B::Deparse; |
10 |
use Carp 'cluck', 'croak'; |
11 |
use B qw(class main_root main_start main_cv svref_2object opnumber |
12 |
OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST |
13 |
OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL |
14 |
OPpLVAL_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE |
15 |
OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY |
16 |
SVf_IOK SVf_NOK SVf_ROK SVf_POK |
17 |
CVf_METHOD CVf_LOCKED CVf_LVALUE |
18 |
PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE |
19 |
PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED); |
20 |
$VERSION = 0.60; |
21 |
use strict; |
22 |
|
23 |
# Changes between 0.50 and 0.51: |
24 |
# - fixed nulled leave with live enter in sort { } |
25 |
# - fixed reference constants (\"str") |
26 |
# - handle empty programs gracefully |
27 |
# - handle infinte loops (for (;;) {}, while (1) {}) |
28 |
# - differentiate between `for my $x ...' and `my $x; for $x ...' |
29 |
# - various minor cleanups |
30 |
# - moved globals into an object |
31 |
# - added `-u', like B::C |
32 |
# - package declarations using cop_stash |
33 |
# - subs, formats and code sorted by cop_seq |
34 |
# Changes between 0.51 and 0.52: |
35 |
# - added pp_threadsv (special variables under USE_THREADS) |
36 |
# - added documentation |
37 |
# Changes between 0.52 and 0.53: |
38 |
# - many changes adding precedence contexts and associativity |
39 |
# - added `-p' and `-s' output style options |
40 |
# - various other minor fixes |
41 |
# Changes between 0.53 and 0.54: |
42 |
# - added support for new `for (1..100)' optimization, |
43 |
# thanks to Gisle Aas |
44 |
# Changes between 0.54 and 0.55: |
45 |
# - added support for new qr// construct |
46 |
# - added support for new pp_regcreset OP |
47 |
# Changes between 0.55 and 0.56: |
48 |
# - tested on base/*.t, cmd/*.t, comp/*.t, io/*.t |
49 |
# - fixed $# on non-lexicals broken in last big rewrite |
50 |
# - added temporary fix for change in opcode of OP_STRINGIFY |
51 |
# - fixed problem in 0.54's for() patch in `for (@ary)' |
52 |
# - fixed precedence in conditional of ?: |
53 |
# - tweaked list paren elimination in `my($x) = @_' |
54 |
# - made continue-block detection trickier wrt. null ops |
55 |
# - fixed various prototype problems in pp_entersub |
56 |
# - added support for sub prototypes that never get GVs |
57 |
# - added unquoting for special filehandle first arg in truncate |
58 |
# - print doubled rv2gv (a bug) as `*{*GV}' instead of illegal `**GV' |
59 |
# - added semicolons at the ends of blocks |
60 |
# - added -l `#line' declaration option -- fixes cmd/subval.t 27,28 |
61 |
# Changes between 0.56 and 0.561: |
62 |
# - fixed multiply-declared my var in pp_truncate (thanks to Sarathy) |
63 |
# - used new B.pm symbolic constants (done by Nick Ing-Simmons) |
64 |
# Changes between 0.561 and 0.57: |
65 |
# - stylistic changes to symbolic constant stuff |
66 |
# - handled scope in s///e replacement code |
67 |
# - added unquote option for expanding "" into concats, etc. |
68 |
# - split method and proto parts of pp_entersub into separate functions |
69 |
# - various minor cleanups |
70 |
# Changes after 0.57: |
71 |
# - added parens in \&foo (patch by Albert Dvornik) |
72 |
# Changes between 0.57 and 0.58: |
73 |
# - fixed `0' statements that weren't being printed |
74 |
# - added methods for use from other programs |
75 |
# (based on patches from James Duncan and Hugo van der Sanden) |
76 |
# - added -si and -sT to control indenting (also based on a patch from Hugo) |
77 |
# - added -sv to print something else instead of '???' |
78 |
# - preliminary version of utf8 tr/// handling |
79 |
# Changes after 0.58: |
80 |
# - uses of $op->ppaddr changed to new $op->name (done by Sarathy) |
81 |
# - added support for Hugo's new OP_SETSTATE (like nextstate) |
82 |
# Changes between 0.58 and 0.59 |
83 |
# - added support for Chip's OP_METHOD_NAMED |
84 |
# - added support for Ilya's OPpTARGET_MY optimization |
85 |
# - elided arrows before `()' subscripts when possible |
86 |
# Changes between 0.59 and 0.60 |
87 |
# - support for method attribues was added |
88 |
# - some warnings fixed |
89 |
# - separate recognition of constant subs |
90 |
# - rewrote continue block handling, now recoginizing for loops |
91 |
# - added more control of expanding control structures |
92 |
|
93 |
# Todo: |
94 |
# - finish tr/// changes |
95 |
# - add option for even more parens (generalize \&foo change) |
96 |
# - {} around variables in strings ("${var}letters") |
97 |
# base/lex.t 25-27 |
98 |
# comp/term.t 11 |
99 |
# - left/right context |
100 |
# - recognize `use utf8', `use integer', etc |
101 |
# - treat top-level block specially for incremental output |
102 |
# - interpret high bit chars in string as utf8 \x{...} (when?) |
103 |
# - copy comments (look at real text with $^P?) |
104 |
# - avoid semis in one-statement blocks |
105 |
# - associativity of &&=, ||=, ?: |
106 |
# - ',' => '=>' (auto-unquote?) |
107 |
# - break long lines ("\r" as discretionary break?) |
108 |
# - configurable syntax highlighting: ANSI color, HTML, TeX, etc. |
109 |
# - more style options: brace style, hex vs. octal, quotes, ... |
110 |
# - print big ints as hex/octal instead of decimal (heuristic?) |
111 |
# - handle `my $x if 0'? |
112 |
# - include values of variables (e.g. set in BEGIN) |
113 |
# - coordinate with Data::Dumper (both directions? see previous) |
114 |
# - version using op_next instead of op_first/sibling? |
115 |
# - avoid string copies (pass arrays, one big join?) |
116 |
# - auto-apply `-u'? |
117 |
# - -uPackage:: descend recursively? |
118 |
# - here-docs? |
119 |
# - <DATA>? |
120 |
|
121 |
# Tests that will always fail: |
122 |
# comp/redef.t -- all (redefinition happens at compile time) |
123 |
|
124 |
# Object fields (were globals): |
125 |
# |
126 |
# avoid_local: |
127 |
# (local($a), local($b)) and local($a, $b) have the same internal |
128 |
# representation but the short form looks better. We notice we can |
129 |
# use a large-scale local when checking the list, but need to prevent |
130 |
# individual locals too. This hash holds the addresses of OPs that |
131 |
# have already had their local-ness accounted for. The same thing |
132 |
# is done with my(). |
133 |
# |
134 |
# curcv: |
135 |
# CV for current sub (or main program) being deparsed |
136 |
# |
137 |
# curstash: |
138 |
# name of the current package for deparsed code |
139 |
# |
140 |
# subs_todo: |
141 |
# array of [cop_seq, GV, is_format?] for subs and formats we still |
142 |
# want to deparse |
143 |
# |
144 |
# protos_todo: |
145 |
# as above, but [name, prototype] for subs that never got a GV |
146 |
# |
147 |
# subs_done, forms_done: |
148 |
# keys are addresses of GVs for subs and formats we've already |
149 |
# deparsed (or at least put into subs_todo) |
150 |
# |
151 |
# parens: -p |
152 |
# linenums: -l |
153 |
# unquote: -q |
154 |
# cuddle: ` ' or `\n', depending on -sC |
155 |
# indent_size: -si |
156 |
# use_tabs: -sT |
157 |
# ex_const: -sv |
158 |
|
159 |
# A little explanation of how precedence contexts and associativity |
160 |
# work: |
161 |
# |
162 |
# deparse() calls each per-op subroutine with an argument $cx (short |
163 |
# for context, but not the same as the cx* in the perl core), which is |
164 |
# a number describing the op's parents in terms of precedence, whether |
165 |
# they're inside an expression or at statement level, etc. (see |
166 |
# chart below). When ops with children call deparse on them, they pass |
167 |
# along their precedence. Fractional values are used to implement |
168 |
# associativity (`($x + $y) + $z' => `$x + $y + $y') and related |
169 |
# parentheses hacks. The major disadvantage of this scheme is that |
170 |
# it doesn't know about right sides and left sides, so say if you |
171 |
# assign a listop to a variable, it can't tell it's allowed to leave |
172 |
# the parens off the listop. |
173 |
|
174 |
# Precedences: |
175 |
# 26 [TODO] inside interpolation context ("") |
176 |
# 25 left terms and list operators (leftward) |
177 |
# 24 left -> |
178 |
# 23 nonassoc ++ -- |
179 |
# 22 right ** |
180 |
# 21 right ! ~ \ and unary + and - |
181 |
# 20 left =~ !~ |
182 |
# 19 left * / % x |
183 |
# 18 left + - . |
184 |
# 17 left << >> |
185 |
# 16 nonassoc named unary operators |
186 |
# 15 nonassoc < > <= >= lt gt le ge |
187 |
# 14 nonassoc == != <=> eq ne cmp |
188 |
# 13 left & |
189 |
# 12 left | ^ |
190 |
# 11 left && |
191 |
# 10 left || |
192 |
# 9 nonassoc .. ... |
193 |
# 8 right ?: |
194 |
# 7 right = += -= *= etc. |
195 |
# 6 left , => |
196 |
# 5 nonassoc list operators (rightward) |
197 |
# 4 right not |
198 |
# 3 left and |
199 |
# 2 left or xor |
200 |
# 1 statement modifiers |
201 |
# 0 statement level |
202 |
|
203 |
# Nonprinting characters with special meaning: |
204 |
# \cS - steal parens (see maybe_parens_unop) |
205 |
# \n - newline and indent |
206 |
# \t - increase indent |
207 |
# \b - decrease indent (`outdent') |
208 |
# \f - flush left (no indent) |
209 |
# \cK - kill following semicolon, if any |
210 |
|
211 |
sub null { |
212 |
my $op = shift; |
213 |
return class($op) eq "NULL"; |
214 |
} |
215 |
|
216 |
sub todo { |
217 |
my $self = shift; |
218 |
my($gv, $cv, $is_form) = @_; |
219 |
my $seq; |
220 |
if (!null($cv->START) and is_state($cv->START)) { |
221 |
$seq = $cv->START->cop_seq; |
222 |
} else { |
223 |
$seq = 0; |
224 |
} |
225 |
push @{$self->{'subs_todo'}}, [$seq, $gv, $is_form]; |
226 |
} |
227 |
|
228 |
sub next_todo { |
229 |
my $self = shift; |
230 |
my $ent = shift @{$self->{'subs_todo'}}; |
231 |
my $name = $self->gv_name($ent->[1]); |
232 |
if ($ent->[2]) { |
233 |
return "format $name =\n" |
234 |
. $self->deparse_format($ent->[1]->FORM). "\n"; |
235 |
} else { |
236 |
return "sub $name " . $self->deparse_sub($ent->[1]->CV); |
237 |
} |
238 |
} |
239 |
|
240 |
sub walk_tree { |
241 |
my($op, $sub) = @_; |
242 |
$sub->($op); |
243 |
if ($op->flags & OPf_KIDS) { |
244 |
my $kid; |
245 |
for ($kid = $op->first; not null $kid; $kid = $kid->sibling) { |
246 |
walk_tree($kid, $sub); |
247 |
} |
248 |
} |
249 |
} |
250 |
|
251 |
sub walk_sub { |
252 |
my $self = shift; |
253 |
my $cv = shift; |
254 |
my $op = $cv->ROOT; |
255 |
$op = shift if null $op; |
256 |
return if !$op or null $op; |
257 |
walk_tree($op, sub { |
258 |
my $op = shift; |
259 |
if ($op->name eq "gv") { |
260 |
my $gv = $self->gv_or_padgv($op); |
261 |
if ($op->next->name eq "entersub") { |
262 |
return if $self->{'subs_done'}{$$gv}++; |
263 |
return if class($gv->CV) eq "SPECIAL"; |
264 |
$self->todo($gv, $gv->CV, 0); |
265 |
$self->walk_sub($gv->CV); |
266 |
} elsif ($op->next->name eq "enterwrite" |
267 |
or ($op->next->name eq "rv2gv" |
268 |
and $op->next->next->name eq "enterwrite")) { |
269 |
return if $self->{'forms_done'}{$$gv}++; |
270 |
return if class($gv->FORM) eq "SPECIAL"; |
271 |
$self->todo($gv, $gv->FORM, 1); |
272 |
$self->walk_sub($gv->FORM); |
273 |
} |
274 |
} |
275 |
}); |
276 |
} |
277 |
|
278 |
sub stash_subs { |
279 |
my $self = shift; |
280 |
my $pack = shift; |
281 |
my(%stash, @ret); |
282 |
{ no strict 'refs'; %stash = svref_2object(\%{$pack . "::"})->ARRAY } |
283 |
if ($pack eq "main") { |
284 |
$pack = ""; |
285 |
} else { |
286 |
$pack = $pack . "::"; |
287 |
} |
288 |
my($key, $val); |
289 |
while (($key, $val) = each %stash) { |
290 |
my $class = class($val); |
291 |
if ($class eq "PV") { |
292 |
# Just a prototype |
293 |
push @{$self->{'protos_todo'}}, [$pack . $key, $val->PV]; |
294 |
} elsif ($class eq "IV") { |
295 |
# Just a name |
296 |
push @{$self->{'protos_todo'}}, [$pack . $key, undef]; |
297 |
} elsif ($class eq "GV") { |
298 |
if (class($val->CV) ne "SPECIAL") { |
299 |
next if $self->{'subs_done'}{$$val}++; |
300 |
$self->todo($val, $val->CV, 0); |
301 |
$self->walk_sub($val->CV); |
302 |
} |
303 |
if (class($val->FORM) ne "SPECIAL") { |
304 |
next if $self->{'forms_done'}{$$val}++; |
305 |
$self->todo($val, $val->FORM, 1); |
306 |
$self->walk_sub($val->FORM); |
307 |
} |
308 |
} |
309 |
} |
310 |
} |
311 |
|
312 |
sub print_protos { |
313 |
my $self = shift; |
314 |
my $ar; |
315 |
my @ret; |
316 |
foreach $ar (@{$self->{'protos_todo'}}) { |
317 |
my $proto = (defined $ar->[1] ? " (". $ar->[1] . ")" : ""); |
318 |
push @ret, "sub " . $ar->[0] . "$proto;\n"; |
319 |
} |
320 |
delete $self->{'protos_todo'}; |
321 |
return @ret; |
322 |
} |
323 |
|
324 |
sub style_opts { |
325 |
my $self = shift; |
326 |
my $opts = shift; |
327 |
my $opt; |
328 |
while (length($opt = substr($opts, 0, 1))) { |
329 |
if ($opt eq "C") { |
330 |
$self->{'cuddle'} = " "; |
331 |
$opts = substr($opts, 1); |
332 |
} elsif ($opt eq "i") { |
333 |
$opts =~ s/^i(\d+)//; |
334 |
$self->{'indent_size'} = $1; |
335 |
} elsif ($opt eq "T") { |
336 |
$self->{'use_tabs'} = 1; |
337 |
$opts = substr($opts, 1); |
338 |
} elsif ($opt eq "v") { |
339 |
$opts =~ s/^v([^.]*)(.|$)//; |
340 |
$self->{'ex_const'} = $1; |
341 |
} |
342 |
} |
343 |
} |
344 |
|
345 |
sub new { |
346 |
my $class = shift; |
347 |
my $self = bless {}, $class; |
348 |
$self->{'subs_todo'} = []; |
349 |
$self->{'curstash'} = "main"; |
350 |
$self->{'cuddle'} = "\n"; |
351 |
$self->{'indent_size'} = 4; |
352 |
$self->{'use_tabs'} = 0; |
353 |
$self->{'expand'} = 0; |
354 |
$self->{'unquote'} = 0; |
355 |
$self->{'linenums'} = 0; |
356 |
$self->{'parens'} = 0; |
357 |
$self->{'ex_const'} = "'???'"; |
358 |
while (my $arg = shift @_) { |
359 |
if (substr($arg, 0, 2) eq "-u") { |
360 |
$self->stash_subs(substr($arg, 2)); |
361 |
} elsif ($arg eq "-p") { |
362 |
$self->{'parens'} = 1; |
363 |
} elsif ($arg eq "-l") { |
364 |
$self->{'linenums'} = 1; |
365 |
} elsif ($arg eq "-q") { |
366 |
$self->{'unquote'} = 1; |
367 |
} elsif (substr($arg, 0, 2) eq "-s") { |
368 |
$self->style_opts(substr $arg, 2); |
369 |
} elsif ($arg =~ /^-x(\d)$/) { |
370 |
$self->{'expand'} = $1; |
371 |
} |
372 |
} |
373 |
return $self; |
374 |
} |
375 |
|
376 |
sub compile { |
377 |
my(@args) = @_; |
378 |
return sub { |
379 |
my $self = B::Deparse->new(@args); |
380 |
$self->stash_subs("main"); |
381 |
$self->{'curcv'} = main_cv; |
382 |
$self->walk_sub(main_cv, main_start); |
383 |
print $self->print_protos; |
384 |
@{$self->{'subs_todo'}} = |
385 |
sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}}; |
386 |
print $self->indent($self->deparse(main_root, 0)), "\n" |
387 |
unless null main_root; |
388 |
my @text; |
389 |
while (scalar(@{$self->{'subs_todo'}})) { |
390 |
push @text, $self->next_todo; |
391 |
} |
392 |
print $self->indent(join("", @text)), "\n" if @text; |
393 |
} |
394 |
} |
395 |
|
396 |
sub coderef2text { |
397 |
my $self = shift; |
398 |
my $sub = shift; |
399 |
croak "Usage: ->coderef2text(CODEREF)" unless ref($sub) eq "CODE"; |
400 |
return $self->indent($self->deparse_sub(svref_2object($sub))); |
401 |
} |
402 |
|
403 |
sub deparse { |
404 |
my $self = shift; |
405 |
my($op, $cx) = @_; |
406 |
# cluck if class($op) eq "NULL"; |
407 |
# cluck unless $op; |
408 |
# return $self->$ {\("pp_" . $op->name)}($op, $cx); |
409 |
my $meth = "pp_" . $op->name; |
410 |
return $self->$meth($op, $cx); |
411 |
} |
412 |
|
413 |
sub indent { |
414 |
my $self = shift; |
415 |
my $txt = shift; |
416 |
my @lines = split(/\n/, $txt); |
417 |
my $leader = ""; |
418 |
my $level = 0; |
419 |
my $line; |
420 |
for $line (@lines) { |
421 |
my $cmd = substr($line, 0, 1); |
422 |
if ($cmd eq "\t" or $cmd eq "\b") { |
423 |
$level += ($cmd eq "\t" ? 1 : -1) * $self->{'indent_size'}; |
424 |
if ($self->{'use_tabs'}) { |
425 |
$leader = "\t" x ($level / 8) . " " x ($level % 8); |
426 |
} else { |
427 |
$leader = " " x $level; |
428 |
} |
429 |
$line = substr($line, 1); |
430 |
} |
431 |
if (substr($line, 0, 1) eq "\f") { |
432 |
$line = substr($line, 1); # no indent |
433 |
} else { |
434 |
$line = $leader . $line; |
435 |
} |
436 |
$line =~ s/\cK;?//g; |
437 |
} |
438 |
return join("\n", @lines); |
439 |
} |
440 |
|
441 |
sub deparse_sub { |
442 |
my $self = shift; |
443 |
my $cv = shift; |
444 |
my $proto = ""; |
445 |
if ($cv->FLAGS & SVf_POK) { |
446 |
$proto = "(". $cv->PV . ") "; |
447 |
} |
448 |
if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) { |
449 |
$proto .= ": "; |
450 |
$proto .= "lvalue " if $cv->CvFLAGS & CVf_LVALUE; |
451 |
$proto .= "locked " if $cv->CvFLAGS & CVf_LOCKED; |
452 |
$proto .= "method " if $cv->CvFLAGS & CVf_METHOD; |
453 |
} |
454 |
|
455 |
local($self->{'curcv'}) = $cv; |
456 |
local($self->{'curstash'}) = $self->{'curstash'}; |
457 |
if (not null $cv->ROOT) { |
458 |
# skip leavesub |
459 |
return $proto . "{\n\t" . |
460 |
$self->deparse($cv->ROOT->first, 0) . "\n\b}\n"; |
461 |
} else { # XSUB? |
462 |
return $proto . "{}\n"; |
463 |
} |
464 |
} |
465 |
|
466 |
sub deparse_format { |
467 |
my $self = shift; |
468 |
my $form = shift; |
469 |
my @text; |
470 |
local($self->{'curcv'}) = $form; |
471 |
local($self->{'curstash'}) = $self->{'curstash'}; |
472 |
my $op = $form->ROOT; |
473 |
my $kid; |
474 |
$op = $op->first->first; # skip leavewrite, lineseq |
475 |
while (not null $op) { |
476 |
$op = $op->sibling; # skip nextstate |
477 |
my @exprs; |
478 |
$kid = $op->first->sibling; # skip pushmark |
479 |
push @text, $self->const_sv($kid)->PV; |
480 |
$kid = $kid->sibling; |
481 |
for (; not null $kid; $kid = $kid->sibling) { |
482 |
push @exprs, $self->deparse($kid, 0); |
483 |
} |
484 |
push @text, join(", ", @exprs)."\n" if @exprs; |
485 |
$op = $op->sibling; |
486 |
} |
487 |
return join("", @text) . "."; |
488 |
} |
489 |
|
490 |
sub is_scope { |
491 |
my $op = shift; |
492 |
return $op->name eq "leave" || $op->name eq "scope" |
493 |
|| $op->name eq "lineseq" |
494 |
|| ($op->name eq "null" && class($op) eq "UNOP" |
495 |
&& (is_scope($op->first) || $op->first->name eq "enter")); |
496 |
} |
497 |
|
498 |
sub is_state { |
499 |
my $name = $_[0]->name; |
500 |
return $name eq "nextstate" || $name eq "dbstate" || $name eq "setstate"; |
501 |
} |
502 |
|
503 |
sub is_miniwhile { # check for one-line loop (`foo() while $y--') |
504 |
my $op = shift; |
505 |
return (!null($op) and null($op->sibling) |
506 |
and $op->name eq "null" and class($op) eq "UNOP" |
507 |
and (($op->first->name =~ /^(and|or)$/ |
508 |
and $op->first->first->sibling->name eq "lineseq") |
509 |
or ($op->first->name eq "lineseq" |
510 |
and not null $op->first->first->sibling |
511 |
and $op->first->first->sibling->name eq "unstack") |
512 |
)); |
513 |
} |
514 |
|
515 |
sub is_scalar { |
516 |
my $op = shift; |
517 |
return ($op->name eq "rv2sv" or |
518 |
$op->name eq "padsv" or |
519 |
$op->name eq "gv" or # only in array/hash constructs |
520 |
$op->flags & OPf_KIDS && !null($op->first) |
521 |
&& $op->first->name eq "gvsv"); |
522 |
} |
523 |
|
524 |
sub maybe_parens { |
525 |
my $self = shift; |
526 |
my($text, $cx, $prec) = @_; |
527 |
if ($prec < $cx # unary ops nest just fine |
528 |
or $prec == $cx and $cx != 4 and $cx != 16 and $cx != 21 |
529 |
or $self->{'parens'}) |
530 |
{ |
531 |
$text = "($text)"; |
532 |
# In a unop, let parent reuse our parens; see maybe_parens_unop |
533 |
$text = "\cS" . $text if $cx == 16; |
534 |
return $text; |
535 |
} else { |
536 |
return $text; |
537 |
} |
538 |
} |
539 |
|
540 |
# same as above, but get around the `if it looks like a function' rule |
541 |
sub maybe_parens_unop { |
542 |
my $self = shift; |
543 |
my($name, $kid, $cx) = @_; |
544 |
if ($cx > 16 or $self->{'parens'}) { |
545 |
return "$name(" . $self->deparse($kid, 1) . ")"; |
546 |
} else { |
547 |
$kid = $self->deparse($kid, 16); |
548 |
if (substr($kid, 0, 1) eq "\cS") { |
549 |
# use kid's parens |
550 |
return $name . substr($kid, 1); |
551 |
} elsif (substr($kid, 0, 1) eq "(") { |
552 |
# avoid looks-like-a-function trap with extra parens |
553 |
# (`+' can lead to ambiguities) |
554 |
return "$name(" . $kid . ")"; |
555 |
} else { |
556 |
return "$name $kid"; |
557 |
} |
558 |
} |
559 |
} |
560 |
|
561 |
sub maybe_parens_func { |
562 |
my $self = shift; |
563 |
my($func, $text, $cx, $prec) = @_; |
564 |
if ($prec <= $cx or substr($text, 0, 1) eq "(" or $self->{'parens'}) { |
565 |
return "$func($text)"; |
566 |
} else { |
567 |
return "$func $text"; |
568 |
} |
569 |
} |
570 |
|
571 |
sub maybe_local { |
572 |
my $self = shift; |
573 |
my($op, $cx, $text) = @_; |
574 |
if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) { |
575 |
if (want_scalar($op)) { |
576 |
return "local $text"; |
577 |
} else { |
578 |
return $self->maybe_parens_func("local", $text, $cx, 16); |
579 |
} |
580 |
} else { |
581 |
return $text; |
582 |
} |
583 |
} |
584 |
|
585 |
sub maybe_targmy { |
586 |
my $self = shift; |
587 |
my($op, $cx, $func, @args) = @_; |
588 |
if ($op->private & OPpTARGET_MY) { |
589 |
my $var = $self->padname($op->targ); |
590 |
my $val = $func->($self, $op, 7, @args); |
591 |
return $self->maybe_parens("$var = $val", $cx, 7); |
592 |
} else { |
593 |
return $func->($self, $op, $cx, @args); |
594 |
} |
595 |
} |
596 |
|
597 |
sub padname_sv { |
598 |
my $self = shift; |
599 |
my $targ = shift; |
600 |
return (($self->{'curcv'}->PADLIST->ARRAY)[0]->ARRAY)[$targ]; |
601 |
} |
602 |
|
603 |
sub maybe_my { |
604 |
my $self = shift; |
605 |
my($op, $cx, $text) = @_; |
606 |
if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) { |
607 |
if (want_scalar($op)) { |
608 |
return "my $text"; |
609 |
} else { |
610 |
return $self->maybe_parens_func("my", $text, $cx, 16); |
611 |
} |
612 |
} else { |
613 |
return $text; |
614 |
} |
615 |
} |
616 |
|
617 |
# The following OPs don't have functions: |
618 |
|
619 |
# pp_padany -- does not exist after parsing |
620 |
# pp_rcatline -- does not exist |
621 |
|
622 |
sub pp_enter { # see also leave |
623 |
cluck "unexpected OP_ENTER"; |
624 |
return "XXX"; |
625 |
} |
626 |
|
627 |
sub pp_pushmark { # see also list |
628 |
cluck "unexpected OP_PUSHMARK"; |
629 |
return "XXX"; |
630 |
} |
631 |
|
632 |
sub pp_leavesub { # see also deparse_sub |
633 |
cluck "unexpected OP_LEAVESUB"; |
634 |
return "XXX"; |
635 |
} |
636 |
|
637 |
sub pp_leavewrite { # see also deparse_format |
638 |
cluck "unexpected OP_LEAVEWRITE"; |
639 |
return "XXX"; |
640 |
} |
641 |
|
642 |
sub pp_method { # see also entersub |
643 |
cluck "unexpected OP_METHOD"; |
644 |
return "XXX"; |
645 |
} |
646 |
|
647 |
sub pp_regcmaybe { # see also regcomp |
648 |
cluck "unexpected OP_REGCMAYBE"; |
649 |
return "XXX"; |
650 |
} |
651 |
|
652 |
sub pp_regcreset { # see also regcomp |
653 |
cluck "unexpected OP_REGCRESET"; |
654 |
return "XXX"; |
655 |
} |
656 |
|
657 |
sub pp_substcont { # see also subst |
658 |
cluck "unexpected OP_SUBSTCONT"; |
659 |
return "XXX"; |
660 |
} |
661 |
|
662 |
sub pp_grepstart { # see also grepwhile |
663 |
cluck "unexpected OP_GREPSTART"; |
664 |
return "XXX"; |
665 |
} |
666 |
|
667 |
sub pp_mapstart { # see also mapwhile |
668 |
cluck "unexpected OP_MAPSTART"; |
669 |
return "XXX"; |
670 |
} |
671 |
|
672 |
sub pp_flip { # see also flop |
673 |
cluck "unexpected OP_FLIP"; |
674 |
return "XXX"; |
675 |
} |
676 |
|
677 |
sub pp_iter { # see also leaveloop |
678 |
cluck "unexpected OP_ITER"; |
679 |
return "XXX"; |
680 |
} |
681 |
|
682 |
sub pp_enteriter { # see also leaveloop |
683 |
cluck "unexpected OP_ENTERITER"; |
684 |
return "XXX"; |
685 |
} |
686 |
|
687 |
sub pp_enterloop { # see also leaveloop |
688 |
cluck "unexpected OP_ENTERLOOP"; |
689 |
return "XXX"; |
690 |
} |
691 |
|
692 |
sub pp_leaveeval { # see also entereval |
693 |
cluck "unexpected OP_LEAVEEVAL"; |
694 |
return "XXX"; |
695 |
} |
696 |
|
697 |
sub pp_entertry { # see also leavetry |
698 |
cluck "unexpected OP_ENTERTRY"; |
699 |
return "XXX"; |
700 |
} |
701 |
|
702 |
sub lineseq { |
703 |
my $self = shift; |
704 |
my(@ops) = @_; |
705 |
my($expr, @exprs); |
706 |
for (my $i = 0; $i < @ops; $i++) { |
707 |
$expr = ""; |
708 |
if (is_state $ops[$i]) { |
709 |
$expr = $self->deparse($ops[$i], 0); |
710 |
$i++; |
711 |
last if $i > $#ops; |
712 |
} |
713 |
if (!is_state $ops[$i] and $ops[$i+1] and !null($ops[$i+1]) and |
714 |
$ops[$i+1]->name eq "leaveloop" and $self->{'expand'} < 3) |
715 |
{ |
716 |
push @exprs, $expr . $self->for_loop($ops[$i], 0); |
717 |
$i++; |
718 |
next; |
719 |
} |
720 |
$expr .= $self->deparse($ops[$i], 0); |
721 |
push @exprs, $expr if length $expr; |
722 |
} |
723 |
return join(";\n", @exprs); |
724 |
} |
725 |
|
726 |
sub scopeop { |
727 |
my($real_block, $self, $op, $cx) = @_; |
728 |
my $kid; |
729 |
my @kids; |
730 |
local($self->{'curstash'}) = $self->{'curstash'} if $real_block; |
731 |
if ($real_block) { |
732 |
$kid = $op->first->sibling; # skip enter |
733 |
if (is_miniwhile($kid)) { |
734 |
my $top = $kid->first; |
735 |
my $name = $top->name; |
736 |
if ($name eq "and") { |
737 |
$name = "while"; |
738 |
} elsif ($name eq "or") { |
739 |
$name = "until"; |
740 |
} else { # no conditional -> while 1 or until 0 |
741 |
return $self->deparse($top->first, 1) . " while 1"; |
742 |
} |
743 |
my $cond = $top->first; |
744 |
my $body = $cond->sibling->first; # skip lineseq |
745 |
$cond = $self->deparse($cond, 1); |
746 |
$body = $self->deparse($body, 1); |
747 |
return "$body $name $cond"; |
748 |
} |
749 |
} else { |
750 |
$kid = $op->first; |
751 |
} |
752 |
for (; !null($kid); $kid = $kid->sibling) { |
753 |
push @kids, $kid; |
754 |
} |
755 |
if ($cx > 0) { # inside an expression, (a do {} while for lineseq) |
756 |
return "do { " . $self->lineseq(@kids) . " }"; |
757 |
} else { |
758 |
return $self->lineseq(@kids) . ";"; |
759 |
} |
760 |
} |
761 |
|
762 |
sub pp_scope { scopeop(0, @_); } |
763 |
sub pp_lineseq { scopeop(0, @_); } |
764 |
sub pp_leave { scopeop(1, @_); } |
765 |
|
766 |
# The BEGIN {} is used here because otherwise this code isn't executed |
767 |
# when you run B::Deparse on itself. |
768 |
my %globalnames; |
769 |
BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC", |
770 |
"ENV", "ARGV", "ARGVOUT", "_"); } |
771 |
|
772 |
sub gv_name { |
773 |
my $self = shift; |
774 |
my $gv = shift; |
775 |
my $stash = $gv->STASH->NAME; |
776 |
my $name = $gv->SAFENAME; |
777 |
if ($stash eq $self->{'curstash'} or $globalnames{$name} |
778 |
or $name =~ /^[^A-Za-z_]/) |
779 |
{ |
780 |
$stash = ""; |
781 |
} else { |
782 |
$stash = $stash . "::"; |
783 |
} |
784 |
if ($name =~ /^\^../) { |
785 |
$name = "{$name}"; # ${^WARNING_BITS} etc |
786 |
} |
787 |
return $stash . $name; |
788 |
} |
789 |
|
790 |
# Notice how subs and formats are inserted between statements here |
791 |
sub pp_nextstate { |
792 |
my $self = shift; |
793 |
my($op, $cx) = @_; |
794 |
my @text; |
795 |
@text = $op->label . ": " if $op->label; |
796 |
my $seq = $op->cop_seq; |
797 |
while (scalar(@{$self->{'subs_todo'}}) |
798 |
and $seq > $self->{'subs_todo'}[0][0]) { |
799 |
push @text, $self->next_todo; |
800 |
} |
801 |
my $stash = $op->stashpv; |
802 |
if ($stash ne $self->{'curstash'}) { |
803 |
push @text, "package $stash;\n"; |
804 |
$self->{'curstash'} = $stash; |
805 |
} |
806 |
if ($self->{'linenums'}) { |
807 |
push @text, "\f#line " . $op->line . |
808 |
' "' . $op->file, qq'"\n'; |
809 |
} |
810 |
return join("", @text); |
811 |
} |
812 |
|
813 |
sub pp_dbstate { pp_nextstate(@_) } |
814 |
sub pp_setstate { pp_nextstate(@_) } |
815 |
|
816 |
sub pp_unstack { return "" } # see also leaveloop |
817 |
|
818 |
sub baseop { |
819 |
my $self = shift; |
820 |
my($op, $cx, $name) = @_; |
821 |
return $name; |
822 |
} |
823 |
|
824 |
sub pp_stub { baseop(@_, "()") } |
825 |
sub pp_wantarray { baseop(@_, "wantarray") } |
826 |
sub pp_fork { baseop(@_, "fork") } |
827 |
sub pp_wait { maybe_targmy(@_, \&baseop, "wait") } |
828 |
sub pp_getppid { maybe_targmy(@_, \&baseop, "getppid") } |
829 |
sub pp_time { maybe_targmy(@_, \&baseop, "time") } |
830 |
sub pp_tms { baseop(@_, "times") } |
831 |
sub pp_ghostent { baseop(@_, "gethostent") } |
832 |
sub pp_gnetent { baseop(@_, "getnetent") } |
833 |
sub pp_gprotoent { baseop(@_, "getprotoent") } |
834 |
sub pp_gservent { baseop(@_, "getservent") } |
835 |
sub pp_ehostent { baseop(@_, "endhostent") } |
836 |
sub pp_enetent { baseop(@_, "endnetent") } |
837 |
sub pp_eprotoent { baseop(@_, "endprotoent") } |
838 |
sub pp_eservent { baseop(@_, "endservent") } |
839 |
sub pp_gpwent { baseop(@_, "getpwent") } |
840 |
sub pp_spwent { baseop(@_, "setpwent") } |
841 |
sub pp_epwent { baseop(@_, "endpwent") } |
842 |
sub pp_ggrent { baseop(@_, "getgrent") } |
843 |
sub pp_sgrent { baseop(@_, "setgrent") } |
844 |
sub pp_egrent { baseop(@_, "endgrent") } |
845 |
sub pp_getlogin { baseop(@_, "getlogin") } |
846 |
|
847 |
sub POSTFIX () { 1 } |
848 |
|
849 |
# I couldn't think of a good short name, but this is the category of |
850 |
# symbolic unary operators with interesting precedence |
851 |
|
852 |
sub pfixop { |
853 |
my $self = shift; |
854 |
my($op, $cx, $name, $prec, $flags) = (@_, 0); |
855 |
my $kid = $op->first; |
856 |
$kid = $self->deparse($kid, $prec); |
857 |
return $self->maybe_parens(($flags & POSTFIX) ? "$kid$name" : "$name$kid", |
858 |
$cx, $prec); |
859 |
} |
860 |
|
861 |
sub pp_preinc { pfixop(@_, "++", 23) } |
862 |
sub pp_predec { pfixop(@_, "--", 23) } |
863 |
sub pp_postinc { maybe_targmy(@_, \&pfixop, "++", 23, POSTFIX) } |
864 |
sub pp_postdec { maybe_targmy(@_, \&pfixop, "--", 23, POSTFIX) } |
865 |
sub pp_i_preinc { pfixop(@_, "++", 23) } |
866 |
sub pp_i_predec { pfixop(@_, "--", 23) } |
867 |
sub pp_i_postinc { maybe_targmy(@_, \&pfixop, "++", 23, POSTFIX) } |
868 |
sub pp_i_postdec { maybe_targmy(@_, \&pfixop, "--", 23, POSTFIX) } |
869 |
sub pp_complement { maybe_targmy(@_, \&pfixop, "~", 21) } |
870 |
|
871 |
sub pp_negate { maybe_targmy(@_, \&real_negate) } |
872 |
sub real_negate { |
873 |
my $self = shift; |
874 |
my($op, $cx) = @_; |
875 |
if ($op->first->name =~ /^(i_)?negate$/) { |
876 |
# avoid --$x |
877 |
$self->pfixop($op, $cx, "-", 21.5); |
878 |
} else { |
879 |
$self->pfixop($op, $cx, "-", 21); |
880 |
} |
881 |
} |
882 |
sub pp_i_negate { pp_negate(@_) } |
883 |
|
884 |
sub pp_not { |
885 |
my $self = shift; |
886 |
my($op, $cx) = @_; |
887 |
if ($cx <= 4) { |
888 |
$self->pfixop($op, $cx, "not ", 4); |
889 |
} else { |
890 |
$self->pfixop($op, $cx, "!", 21); |
891 |
} |
892 |
} |
893 |
|
894 |
sub unop { |
895 |
my $self = shift; |
896 |
my($op, $cx, $name) = @_; |
897 |
my $kid; |
898 |
if ($op->flags & OPf_KIDS) { |
899 |
$kid = $op->first; |
900 |
return $self->maybe_parens_unop($name, $kid, $cx); |
901 |
} else { |
902 |
return $name . ($op->flags & OPf_SPECIAL ? "()" : ""); |
903 |
} |
904 |
} |
905 |
|
906 |
sub pp_chop { maybe_targmy(@_, \&unop, "chop") } |
907 |
sub pp_chomp { maybe_targmy(@_, \&unop, "chomp") } |
908 |
sub pp_schop { maybe_targmy(@_, \&unop, "chop") } |
909 |
sub pp_schomp { maybe_targmy(@_, \&unop, "chomp") } |
910 |
sub pp_defined { unop(@_, "defined") } |
911 |
sub pp_undef { unop(@_, "undef") } |
912 |
sub pp_study { unop(@_, "study") } |
913 |
sub pp_ref { unop(@_, "ref") } |
914 |
sub pp_pos { maybe_local(@_, unop(@_, "pos")) } |
915 |
|
916 |
sub pp_sin { maybe_targmy(@_, \&unop, "sin") } |
917 |
sub pp_cos { maybe_targmy(@_, \&unop, "cos") } |
918 |
sub pp_rand { maybe_targmy(@_, \&unop, "rand") } |
919 |
sub pp_srand { unop(@_, "srand") } |
920 |
sub pp_exp { maybe_targmy(@_, \&unop, "exp") } |
921 |
sub pp_log { maybe_targmy(@_, \&unop, "log") } |
922 |
sub pp_sqrt { maybe_targmy(@_, \&unop, "sqrt") } |
923 |
sub pp_int { maybe_targmy(@_, \&unop, "int") } |
924 |
sub pp_hex { maybe_targmy(@_, \&unop, "hex") } |
925 |
sub pp_oct { maybe_targmy(@_, \&unop, "oct") } |
926 |
sub pp_abs { maybe_targmy(@_, \&unop, "abs") } |
927 |
|
928 |
sub pp_length { maybe_targmy(@_, \&unop, "length") } |
929 |
sub pp_ord { maybe_targmy(@_, \&unop, "ord") } |
930 |
sub pp_chr { maybe_targmy(@_, \&unop, "chr") } |
931 |
|
932 |
sub pp_each { unop(@_, "each") } |
933 |
sub pp_values { unop(@_, "values") } |
934 |
sub pp_keys { unop(@_, "keys") } |
935 |
sub pp_pop { unop(@_, "pop") } |
936 |
sub pp_shift { unop(@_, "shift") } |
937 |
|
938 |
sub pp_caller { unop(@_, "caller") } |
939 |
sub pp_reset { unop(@_, "reset") } |
940 |
sub pp_exit { unop(@_, "exit") } |
941 |
sub pp_prototype { unop(@_, "prototype") } |
942 |
|
943 |
sub pp_close { unop(@_, "close") } |
944 |
sub pp_fileno { unop(@_, "fileno") } |
945 |
sub pp_umask { unop(@_, "umask") } |
946 |
sub pp_untie { unop(@_, "untie") } |
947 |
sub pp_tied { unop(@_, "tied") } |
948 |
sub pp_dbmclose { unop(@_, "dbmclose") } |
949 |
sub pp_getc { unop(@_, "getc") } |
950 |
sub pp_eof { unop(@_, "eof") } |
951 |
sub pp_tell { unop(@_, "tell") } |
952 |
sub pp_getsockname { unop(@_, "getsockname") } |
953 |
sub pp_getpeername { unop(@_, "getpeername") } |
954 |
|
955 |
sub pp_chdir { maybe_targmy(@_, \&unop, "chdir") } |
956 |
sub pp_chroot { maybe_targmy(@_, \&unop, "chroot") } |
957 |
sub pp_readlink { unop(@_, "readlink") } |
958 |
sub pp_rmdir { maybe_targmy(@_, \&unop, "rmdir") } |
959 |
sub pp_readdir { unop(@_, "readdir") } |
960 |
sub pp_telldir { unop(@_, "telldir") } |
961 |
sub pp_rewinddir { unop(@_, "rewinddir") } |
962 |
sub pp_closedir { unop(@_, "closedir") } |
963 |
sub pp_getpgrp { maybe_targmy(@_, \&unop, "getpgrp") } |
964 |
sub pp_localtime { unop(@_, "localtime") } |
965 |
sub pp_gmtime { unop(@_, "gmtime") } |
966 |
sub pp_alarm { unop(@_, "alarm") } |
967 |
sub pp_sleep { maybe_targmy(@_, \&unop, "sleep") } |
968 |
|
969 |
sub pp_dofile { unop(@_, "do") } |
970 |
sub pp_entereval { unop(@_, "eval") } |
971 |
|
972 |
sub pp_ghbyname { unop(@_, "gethostbyname") } |
973 |
sub pp_gnbyname { unop(@_, "getnetbyname") } |
974 |
sub pp_gpbyname { unop(@_, "getprotobyname") } |
975 |
sub pp_shostent { unop(@_, "sethostent") } |
976 |
sub pp_snetent { unop(@_, "setnetent") } |
977 |
sub pp_sprotoent { unop(@_, "setprotoent") } |
978 |
sub pp_sservent { unop(@_, "setservent") } |
979 |
sub pp_gpwnam { unop(@_, "getpwnam") } |
980 |
sub pp_gpwuid { unop(@_, "getpwuid") } |
981 |
sub pp_ggrnam { unop(@_, "getgrnam") } |
982 |
sub pp_ggrgid { unop(@_, "getgrgid") } |
983 |
|
984 |
sub pp_lock { unop(@_, "lock") } |
985 |
|
986 |
sub pp_exists { |
987 |
my $self = shift; |
988 |
my($op, $cx) = @_; |
989 |
return $self->maybe_parens_func("exists", $self->pp_helem($op->first, 16), |
990 |
$cx, 16); |
991 |
} |
992 |
|
993 |
sub pp_delete { |
994 |
my $self = shift; |
995 |
my($op, $cx) = @_; |
996 |
my $arg; |
997 |
if ($op->private & OPpSLICE) { |
998 |
return $self->maybe_parens_func("delete", |
999 |
$self->pp_hslice($op->first, 16), |
1000 |
$cx, 16); |
1001 |
} else { |
1002 |
return $self->maybe_parens_func("delete", |
1003 |
$self->pp_helem($op->first, 16), |
1004 |
$cx, 16); |
1005 |
} |
1006 |
} |
1007 |
|
1008 |
sub pp_require { |
1009 |
my $self = shift; |
1010 |
my($op, $cx) = @_; |
1011 |
if (class($op) eq "UNOP" and $op->first->name eq "const" |
1012 |
and $op->first->private & OPpCONST_BARE) |
1013 |
{ |
1014 |
my $name = $self->const_sv($op->first)->PV; |
1015 |
$name =~ s[/][::]g; |
1016 |
$name =~ s/\.pm//g; |
1017 |
return "require($name)"; |
1018 |
} else { |
1019 |
$self->unop($op, $cx, "require"); |
1020 |
} |
1021 |
} |
1022 |
|
1023 |
sub pp_scalar { |
1024 |
my $self = shift; |
1025 |
my($op, $cv) = @_; |
1026 |
my $kid = $op->first; |
1027 |
if (not null $kid->sibling) { |
1028 |
# XXX Was a here-doc |
1029 |
return $self->dquote($op); |
1030 |
} |
1031 |
$self->unop(@_, "scalar"); |
1032 |
} |
1033 |
|
1034 |
|
1035 |
sub padval { |
1036 |
my $self = shift; |
1037 |
my $targ = shift; |
1038 |
#cluck "curcv was undef" unless $self->{curcv}; |
1039 |
return (($self->{'curcv'}->PADLIST->ARRAY)[1]->ARRAY)[$targ]; |
1040 |
} |
1041 |
|
1042 |
sub pp_refgen { |
1043 |
my $self = shift; |
1044 |
my($op, $cx) = @_; |
1045 |
my $kid = $op->first; |
1046 |
if ($kid->name eq "null") { |
1047 |
$kid = $kid->first; |
1048 |
if ($kid->name eq "anonlist" || $kid->name eq "anonhash") { |
1049 |
my($pre, $post) = @{{"anonlist" => ["[","]"], |
1050 |
"anonhash" => ["{","}"]}->{$kid->name}}; |
1051 |
my($expr, @exprs); |
1052 |
$kid = $kid->first->sibling; # skip pushmark |
1053 |
for (; !null($kid); $kid = $kid->sibling) { |
1054 |
$expr = $self->deparse($kid, 6); |
1055 |
push @exprs, $expr; |
1056 |
} |
1057 |
return $pre . join(", ", @exprs) . $post; |
1058 |
} elsif (!null($kid->sibling) and |
1059 |
$kid->sibling->name eq "anoncode") { |
1060 |
return "sub " . |
1061 |
$self->deparse_sub($self->padval($kid->sibling->targ)); |
1062 |
} elsif ($kid->name eq "pushmark") { |
1063 |
my $sib_name = $kid->sibling->name; |
1064 |
if ($sib_name =~ /^(pad|rv2)[ah]v$/ |
1065 |
and not $kid->sibling->flags & OPf_REF) |
1066 |
{ |
1067 |
# The @a in \(@a) isn't in ref context, but only when the |
1068 |
# parens are there. |
1069 |
return "\\(" . $self->deparse($kid->sibling, 1) . ")"; |
1070 |
} elsif ($sib_name eq 'entersub') { |
1071 |
my $text = $self->deparse($kid->sibling, 1); |
1072 |
# Always show parens for \(&func()), but only with -p otherwise |
1073 |
$text = "($text)" if $self->{'parens'} |
1074 |
or $kid->sibling->private & OPpENTERSUB_AMPER; |
1075 |
return "\\$text"; |
1076 |
} |
1077 |
} |
1078 |
} |
1079 |
$self->pfixop($op, $cx, "\\", 20); |
1080 |
} |
1081 |
|
1082 |
sub pp_srefgen { pp_refgen(@_) } |
1083 |
|
1084 |
sub pp_readline { |
1085 |
my $self = shift; |
1086 |
my($op, $cx) = @_; |
1087 |
my $kid = $op->first; |
1088 |
$kid = $kid->first if $kid->name eq "rv2gv"; # <$fh> |
1089 |
return "<" . $self->deparse($kid, 1) . ">"; |
1090 |
} |
1091 |
|
1092 |
# Unary operators that can occur as pseudo-listops inside double quotes |
1093 |
sub dq_unop { |
1094 |
my $self = shift; |
1095 |
my($op, $cx, $name, $prec, $flags) = (@_, 0, 0); |
1096 |
my $kid; |
1097 |
if ($op->flags & OPf_KIDS) { |
1098 |
$kid = $op->first; |
1099 |
# If there's more than one kid, the first is an ex-pushmark. |
1100 |
$kid = $kid->sibling if not null $kid->sibling; |
1101 |
return $self->maybe_parens_unop($name, $kid, $cx); |
1102 |
} else { |
1103 |
return $name . ($op->flags & OPf_SPECIAL ? "()" : ""); |
1104 |
} |
1105 |
} |
1106 |
|
1107 |
sub pp_ucfirst { dq_unop(@_, "ucfirst") } |
1108 |
sub pp_lcfirst { dq_unop(@_, "lcfirst") } |
1109 |
sub pp_uc { dq_unop(@_, "uc") } |
1110 |
sub pp_lc { dq_unop(@_, "lc") } |
1111 |
sub pp_quotemeta { maybe_targmy(@_, \&dq_unop, "quotemeta") } |
1112 |
|
1113 |
sub loopex { |
1114 |
my $self = shift; |
1115 |
my ($op, $cx, $name) = @_; |
1116 |
if (class($op) eq "PVOP") { |
1117 |
return "$name " . $op->pv; |
1118 |
} elsif (class($op) eq "OP") { |
1119 |
return $name; |
1120 |
} elsif (class($op) eq "UNOP") { |
1121 |
# Note -- loop exits are actually exempt from the |
1122 |
# looks-like-a-func rule, but a few extra parens won't hurt |
1123 |
return $self->maybe_parens_unop($name, $op->first, $cx); |
1124 |
} |
1125 |
} |
1126 |
|
1127 |
sub pp_last { loopex(@_, "last") } |
1128 |
sub pp_next { loopex(@_, "next") } |
1129 |
sub pp_redo { loopex(@_, "redo") } |
1130 |
sub pp_goto { loopex(@_, "goto") } |
1131 |
sub pp_dump { loopex(@_, "dump") } |
1132 |
|
1133 |
sub ftst { |
1134 |
my $self = shift; |
1135 |
my($op, $cx, $name) = @_; |
1136 |
if (class($op) eq "UNOP") { |
1137 |
# Genuine `-X' filetests are exempt from the LLAFR, but not |
1138 |
# l?stat(); for the sake of clarity, give'em all parens |
1139 |
return $self->maybe_parens_unop($name, $op->first, $cx); |
1140 |
} elsif (class($op) eq "SVOP") { |
1141 |
return $self->maybe_parens_func($name, $self->pp_gv($op, 1), $cx, 16); |
1142 |
} else { # I don't think baseop filetests ever survive ck_ftst, but... |
1143 |
return $name; |
1144 |
} |
1145 |
} |
1146 |
|
1147 |
sub pp_lstat { ftst(@_, "lstat") } |
1148 |
sub pp_stat { ftst(@_, "stat") } |
1149 |
sub pp_ftrread { ftst(@_, "-R") } |
1150 |
sub pp_ftrwrite { ftst(@_, "-W") } |
1151 |
sub pp_ftrexec { ftst(@_, "-X") } |
1152 |
sub pp_fteread { ftst(@_, "-r") } |
1153 |
sub pp_ftewrite { ftst(@_, "-r") } |
1154 |
sub pp_fteexec { ftst(@_, "-r") } |
1155 |
sub pp_ftis { ftst(@_, "-e") } |
1156 |
sub pp_fteowned { ftst(@_, "-O") } |
1157 |
sub pp_ftrowned { ftst(@_, "-o") } |
1158 |
sub pp_ftzero { ftst(@_, "-z") } |
1159 |
sub pp_ftsize { ftst(@_, "-s") } |
1160 |
sub pp_ftmtime { ftst(@_, "-M") } |
1161 |
sub pp_ftatime { ftst(@_, "-A") } |
1162 |
sub pp_ftctime { ftst(@_, "-C") } |
1163 |
sub pp_ftsock { ftst(@_, "-S") } |
1164 |
sub pp_ftchr { ftst(@_, "-c") } |
1165 |
sub pp_ftblk { ftst(@_, "-b") } |
1166 |
sub pp_ftfile { ftst(@_, "-f") } |
1167 |
sub pp_ftdir { ftst(@_, "-d") } |
1168 |
sub pp_ftpipe { ftst(@_, "-p") } |
1169 |
sub pp_ftlink { ftst(@_, "-l") } |
1170 |
sub pp_ftsuid { ftst(@_, "-u") } |
1171 |
sub pp_ftsgid { ftst(@_, "-g") } |
1172 |
sub pp_ftsvtx { ftst(@_, "-k") } |
1173 |
sub pp_fttty { ftst(@_, "-t") } |
1174 |
sub pp_fttext { ftst(@_, "-T") } |
1175 |
sub pp_ftbinary { ftst(@_, "-B") } |
1176 |
|
1177 |
sub SWAP_CHILDREN () { 1 } |
1178 |
sub ASSIGN () { 2 } # has OP= variant |
1179 |
|
1180 |
my(%left, %right); |
1181 |
|
1182 |
sub assoc_class { |
1183 |
my $op = shift; |
1184 |
my $name = $op->name; |
1185 |
if ($name eq "concat" and $op->first->name eq "concat") { |
1186 |
# avoid spurious `=' -- see comment in pp_concat |
1187 |
return "concat"; |
1188 |
} |
1189 |
if ($name eq "null" and class($op) eq "UNOP" |
1190 |
and $op->first->name =~ /^(and|x?or)$/ |
1191 |
and null $op->first->sibling) |
1192 |
{ |
1193 |
# Like all conditional constructs, OP_ANDs and OP_ORs are topped |
1194 |
# with a null that's used as the common end point of the two |
1195 |
# flows of control. For precedence purposes, ignore it. |
1196 |
# (COND_EXPRs have these too, but we don't bother with |
1197 |
# their associativity). |
1198 |
return assoc_class($op->first); |
1199 |
} |
1200 |
return $name . ($op->flags & OPf_STACKED ? "=" : ""); |
1201 |
} |
1202 |
|
1203 |
# Left associative operators, like `+', for which |
1204 |
# $a + $b + $c is equivalent to ($a + $b) + $c |
1205 |
|
1206 |
BEGIN { |
1207 |
%left = ('multiply' => 19, 'i_multiply' => 19, |
1208 |
'divide' => 19, 'i_divide' => 19, |
1209 |
'modulo' => 19, 'i_modulo' => 19, |
1210 |
'repeat' => 19, |
1211 |
'add' => 18, 'i_add' => 18, |
1212 |
'subtract' => 18, 'i_subtract' => 18, |
1213 |
'concat' => 18, |
1214 |
'left_shift' => 17, 'right_shift' => 17, |
1215 |
'bit_and' => 13, |
1216 |
'bit_or' => 12, 'bit_xor' => 12, |
1217 |
'and' => 3, |
1218 |
'or' => 2, 'xor' => 2, |
1219 |
); |
1220 |
} |
1221 |
|
1222 |
sub deparse_binop_left { |
1223 |
my $self = shift; |
1224 |
my($op, $left, $prec) = @_; |
1225 |
if ($left{assoc_class($op)} && $left{assoc_class($left)} |
1226 |
and $left{assoc_class($op)} == $left{assoc_class($left)}) |
1227 |
{ |
1228 |
return $self->deparse($left, $prec - .00001); |
1229 |
} else { |
1230 |
return $self->deparse($left, $prec); |
1231 |
} |
1232 |
} |
1233 |
|
1234 |
# Right associative operators, like `=', for which |
1235 |
# $a = $b = $c is equivalent to $a = ($b = $c) |
1236 |
|
1237 |
BEGIN { |
1238 |
%right = ('pow' => 22, |
1239 |
'sassign=' => 7, 'aassign=' => 7, |
1240 |
'multiply=' => 7, 'i_multiply=' => 7, |
1241 |
'divide=' => 7, 'i_divide=' => 7, |
1242 |
'modulo=' => 7, 'i_modulo=' => 7, |
1243 |
'repeat=' => 7, |
1244 |
'add=' => 7, 'i_add=' => 7, |
1245 |
'subtract=' => 7, 'i_subtract=' => 7, |
1246 |
'concat=' => 7, |
1247 |
'left_shift=' => 7, 'right_shift=' => 7, |
1248 |
'bit_and=' => 7, |
1249 |
'bit_or=' => 7, 'bit_xor=' => 7, |
1250 |
'andassign' => 7, |
1251 |
'orassign' => 7, |
1252 |
); |
1253 |
} |
1254 |
|
1255 |
sub deparse_binop_right { |
1256 |
my $self = shift; |
1257 |
my($op, $right, $prec) = @_; |
1258 |
if ($right{assoc_class($op)} && $right{assoc_class($right)} |
1259 |
and $right{assoc_class($op)} == $right{assoc_class($right)}) |
1260 |
{ |
1261 |
return $self->deparse($right, $prec - .00001); |
1262 |
} else { |
1263 |
return $self->deparse($right, $prec); |
1264 |
} |
1265 |
} |
1266 |
|
1267 |
sub binop { |
1268 |
my $self = shift; |
1269 |
my ($op, $cx, $opname, $prec, $flags) = (@_, 0); |
1270 |
my $left = $op->first; |
1271 |
my $right = $op->last; |
1272 |
my $eq = ""; |
1273 |
if ($op->flags & OPf_STACKED && $flags & ASSIGN) { |
1274 |
$eq = "="; |
1275 |
$prec = 7; |
1276 |
} |
1277 |
if ($flags & SWAP_CHILDREN) { |
1278 |
($left, $right) = ($right, $left); |
1279 |
} |
1280 |
$left = $self->deparse_binop_left($op, $left, $prec); |
1281 |
$right = $self->deparse_binop_right($op, $right, $prec); |
1282 |
return $self->maybe_parens("$left $opname$eq $right", $cx, $prec); |
1283 |
} |
1284 |
|
1285 |
sub pp_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) } |
1286 |
sub pp_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) } |
1287 |
sub pp_subtract { maybe_targmy(@_, \&binop, "-",18, ASSIGN) } |
1288 |
sub pp_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) } |
1289 |
sub pp_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) } |
1290 |
sub pp_i_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) } |
1291 |
sub pp_i_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) } |
1292 |
sub pp_i_subtract { maybe_targmy(@_, \&binop, "-", 18, ASSIGN) } |
1293 |
sub pp_i_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) } |
1294 |
sub pp_i_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) } |
1295 |
sub pp_pow { maybe_targmy(@_, \&binop, "**", 22, ASSIGN) } |
1296 |
|
1297 |
sub pp_left_shift { maybe_targmy(@_, \&binop, "<<", 17, ASSIGN) } |
1298 |
sub pp_right_shift { maybe_targmy(@_, \&binop, ">>", 17, ASSIGN) } |
1299 |
sub pp_bit_and { maybe_targmy(@_, \&binop, "&", 13, ASSIGN) } |
1300 |
sub pp_bit_or { maybe_targmy(@_, \&binop, "|", 12, ASSIGN) } |
1301 |
sub pp_bit_xor { maybe_targmy(@_, \&binop, "^", 12, ASSIGN) } |
1302 |
|
1303 |
sub pp_eq { binop(@_, "==", 14) } |
1304 |
sub pp_ne { binop(@_, "!=", 14) } |
1305 |
sub pp_lt { binop(@_, "<", 15) } |
1306 |
sub pp_gt { binop(@_, ">", 15) } |
1307 |
sub pp_ge { binop(@_, ">=", 15) } |
1308 |
sub pp_le { binop(@_, "<=", 15) } |
1309 |
sub pp_ncmp { binop(@_, "<=>", 14) } |
1310 |
sub pp_i_eq { binop(@_, "==", 14) } |
1311 |
sub pp_i_ne { binop(@_, "!=", 14) } |
1312 |
sub pp_i_lt { binop(@_, "<", 15) } |
1313 |
sub pp_i_gt { binop(@_, ">", 15) } |
1314 |
sub pp_i_ge { binop(@_, ">=", 15) } |
1315 |
sub pp_i_le { binop(@_, "<=", 15) } |
1316 |
sub pp_i_ncmp { binop(@_, "<=>", 14) } |
1317 |
|
1318 |
sub pp_seq { binop(@_, "eq", 14) } |
1319 |
sub pp_sne { binop(@_, "ne", 14) } |
1320 |
sub pp_slt { binop(@_, "lt", 15) } |
1321 |
sub pp_sgt { binop(@_, "gt", 15) } |
1322 |
sub pp_sge { binop(@_, "ge", 15) } |
1323 |
sub pp_sle { binop(@_, "le", 15) } |
1324 |
sub pp_scmp { binop(@_, "cmp", 14) } |
1325 |
|
1326 |
sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) } |
1327 |
sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN) } |
1328 |
|
1329 |
# `.' is special because concats-of-concats are optimized to save copying |
1330 |
# by making all but the first concat stacked. The effect is as if the |
1331 |
# programmer had written `($a . $b) .= $c', except legal. |
1332 |
sub pp_concat { maybe_targmy(@_, \&real_concat) } |
1333 |
sub real_concat { |
1334 |
my $self = shift; |
1335 |
my($op, $cx) = @_; |
1336 |
my $left = $op->first; |
1337 |
my $right = $op->last; |
1338 |
my $eq = ""; |
1339 |
my $prec = 18; |
1340 |
if ($op->flags & OPf_STACKED and $op->first->name ne "concat") { |
1341 |
$eq = "="; |
1342 |
$prec = 7; |
1343 |
} |
1344 |
$left = $self->deparse_binop_left($op, $left, $prec); |
1345 |
$right = $self->deparse_binop_right($op, $right, $prec); |
1346 |
return $self->maybe_parens("$left .$eq $right", $cx, $prec); |
1347 |
} |
1348 |
|
1349 |
# `x' is weird when the left arg is a list |
1350 |
sub pp_repeat { |
1351 |
my $self = shift; |
1352 |
my($op, $cx) = @_; |
1353 |
my $left = $op->first; |
1354 |
my $right = $op->last; |
1355 |
my $eq = ""; |
1356 |
my $prec = 19; |
1357 |
if ($op->flags & OPf_STACKED) { |
1358 |
$eq = "="; |
1359 |
$prec = 7; |
1360 |
} |
1361 |
if (null($right)) { # list repeat; count is inside left-side ex-list |
1362 |
my $kid = $left->first->sibling; # skip pushmark |
1363 |
my @exprs; |
1364 |
for (; !null($kid->sibling); $kid = $kid->sibling) { |
1365 |
push @exprs, $self->deparse($kid, 6); |
1366 |
} |
1367 |
$right = $kid; |
1368 |
$left = "(" . join(", ", @exprs). ")"; |
1369 |
} else { |
1370 |
$left = $self->deparse_binop_left($op, $left, $prec); |
1371 |
} |
1372 |
$right = $self->deparse_binop_right($op, $right, $prec); |
1373 |
return $self->maybe_parens("$left x$eq $right", $cx, $prec); |
1374 |
} |
1375 |
|
1376 |
sub range { |
1377 |
my $self = shift; |
1378 |
my ($op, $cx, $type) = @_; |
1379 |
my $left = $op->first; |
1380 |
my $right = $left->sibling; |
1381 |
$left = $self->deparse($left, 9); |
1382 |
$right = $self->deparse($right, 9); |
1383 |
return $self->maybe_parens("$left $type $right", $cx, 9); |
1384 |
} |
1385 |
|
1386 |
sub pp_flop { |
1387 |
my $self = shift; |
1388 |
my($op, $cx) = @_; |
1389 |
my $flip = $op->first; |
1390 |
my $type = ($flip->flags & OPf_SPECIAL) ? "..." : ".."; |
1391 |
return $self->range($flip->first, $cx, $type); |
1392 |
} |
1393 |
|
1394 |
# one-line while/until is handled in pp_leave |
1395 |
|
1396 |
sub logop { |
1397 |
my $self = shift; |
1398 |
my ($op, $cx, $lowop, $lowprec, $highop, $highprec, $blockname) = @_; |
1399 |
my $left = $op->first; |
1400 |
my $right = $op->first->sibling; |
1401 |
if ($cx == 0 and is_scope($right) and $blockname |
1402 |
and $self->{'expand'} < 7) |
1403 |
{ # if ($a) {$b} |
1404 |
$left = $self->deparse($left, 1); |
1405 |
$right = $self->deparse($right, 0); |
1406 |
return "$blockname ($left) {\n\t$right\n\b}\cK"; |
1407 |
} elsif ($cx == 0 and $blockname and not $self->{'parens'} |
1408 |
and $self->{'expand'} < 7) { # $b if $a |
1409 |
$right = $self->deparse($right, 1); |
1410 |
$left = $self->deparse($left, 1); |
1411 |
return "$right $blockname $left"; |
1412 |
} elsif ($cx > $lowprec and $highop) { # $a && $b |
1413 |
$left = $self->deparse_binop_left($op, $left, $highprec); |
1414 |
$right = $self->deparse_binop_right($op, $right, $highprec); |
1415 |
return $self->maybe_parens("$left $highop $right", $cx, $highprec); |
1416 |
} else { # $a and $b |
1417 |
$left = $self->deparse_binop_left($op, $left, $lowprec); |
1418 |
$right = $self->deparse_binop_right($op, $right, $lowprec); |
1419 |
return $self->maybe_parens("$left $lowop $right", $cx, $lowprec); |
1420 |
} |
1421 |
} |
1422 |
|
1423 |
sub pp_and { logop(@_, "and", 3, "&&", 11, "if") } |
1424 |
sub pp_or { logop(@_, "or", 2, "||", 10, "unless") } |
1425 |
|
1426 |
# xor is syntactically a logop, but it's really a binop (contrary to |
1427 |
# old versions of opcode.pl). Syntax is what matters here. |
1428 |
sub pp_xor { logop(@_, "xor", 2, "", 0, "") } |
1429 |
|
1430 |
sub logassignop { |
1431 |
my $self = shift; |
1432 |
my ($op, $cx, $opname) = @_; |
1433 |
my $left = $op->first; |
1434 |
my $right = $op->first->sibling->first; # skip sassign |
1435 |
$left = $self->deparse($left, 7); |
1436 |
$right = $self->deparse($right, 7); |
1437 |
return $self->maybe_parens("$left $opname $right", $cx, 7); |
1438 |
} |
1439 |
|
1440 |
sub pp_andassign { logassignop(@_, "&&=") } |
1441 |
sub pp_orassign { logassignop(@_, "||=") } |
1442 |
|
1443 |
sub listop { |
1444 |
my $self = shift; |
1445 |
my($op, $cx, $name) = @_; |
1446 |
my(@exprs); |
1447 |
my $parens = ($cx >= 5) || $self->{'parens'}; |
1448 |
my $kid = $op->first->sibling; |
1449 |
return $name if null $kid; |
1450 |
my $first = $self->deparse($kid, 6); |
1451 |
$first = "+$first" if not $parens and substr($first, 0, 1) eq "("; |
1452 |
push @exprs, $first; |
1453 |
$kid = $kid->sibling; |
1454 |
for (; !null($kid); $kid = $kid->sibling) { |
1455 |
push @exprs, $self->deparse($kid, 6); |
1456 |
} |
1457 |
if ($parens) { |
1458 |
return "$name(" . join(", ", @exprs) . ")"; |
1459 |
} else { |
1460 |
return "$name " . join(", ", @exprs); |
1461 |
} |
1462 |
} |
1463 |
|
1464 |
sub pp_bless { listop(@_, "bless") } |
1465 |
sub pp_atan2 { maybe_targmy(@_, \&listop, "atan2") } |
1466 |
sub pp_substr { maybe_local(@_, listop(@_, "substr")) } |
1467 |
sub pp_vec { maybe_local(@_, listop(@_, "vec")) } |
1468 |
sub pp_index { maybe_targmy(@_, \&listop, "index") } |
1469 |
sub pp_rindex { maybe_targmy(@_, \&listop, "rindex") } |
1470 |
sub pp_sprintf { maybe_targmy(@_, \&listop, "sprintf") } |
1471 |
sub pp_formline { listop(@_, "formline") } # see also deparse_format |
1472 |
sub pp_crypt { maybe_targmy(@_, \&listop, "crypt") } |
1473 |
sub pp_unpack { listop(@_, "unpack") } |
1474 |
sub pp_pack { listop(@_, "pack") } |
1475 |
sub pp_join { maybe_targmy(@_, \&listop, "join") } |
1476 |
sub pp_splice { listop(@_, "splice") } |
1477 |
sub pp_push { maybe_targmy(@_, \&listop, "push") } |
1478 |
sub pp_unshift { maybe_targmy(@_, \&listop, "unshift") } |
1479 |
sub pp_reverse { listop(@_, "reverse") } |
1480 |
sub pp_warn { listop(@_, "warn") } |
1481 |
sub pp_die { listop(@_, "die") } |
1482 |
# Actually, return is exempt from the LLAFR (see examples in this very |
1483 |
# module!), but for consistency's sake, ignore that fact |
1484 |
sub pp_return { listop(@_, "return") } |
1485 |
sub pp_open { listop(@_, "open") } |
1486 |
sub pp_pipe_op { listop(@_, "pipe") } |
1487 |
sub pp_tie { listop(@_, "tie") } |
1488 |
sub pp_binmode { listop(@_, "binmode") } |
1489 |
sub pp_dbmopen { listop(@_, "dbmopen") } |
1490 |
sub pp_sselect { listop(@_, "select") } |
1491 |
sub pp_select { listop(@_, "select") } |
1492 |
sub pp_read { listop(@_, "read") } |
1493 |
sub pp_sysopen { listop(@_, "sysopen") } |
1494 |
sub pp_sysseek { listop(@_, "sysseek") } |
1495 |
sub pp_sysread { listop(@_, "sysread") } |
1496 |
sub pp_syswrite { listop(@_, "syswrite") } |
1497 |
sub pp_send { listop(@_, "send") } |
1498 |
sub pp_recv { listop(@_, "recv") } |
1499 |
sub pp_seek { listop(@_, "seek") } |
1500 |
sub pp_fcntl { listop(@_, "fcntl") } |
1501 |
sub pp_ioctl { listop(@_, "ioctl") } |
1502 |
sub pp_flock { maybe_targmy(@_, \&listop, "flock") } |
1503 |
sub pp_socket { listop(@_, "socket") } |
1504 |
sub pp_sockpair { listop(@_, "sockpair") } |
1505 |
sub pp_bind { listop(@_, "bind") } |
1506 |
sub pp_connect { listop(@_, "connect") } |
1507 |
sub pp_listen { listop(@_, "listen") } |
1508 |
sub pp_accept { listop(@_, "accept") } |
1509 |
sub pp_shutdown { listop(@_, "shutdown") } |
1510 |
sub pp_gsockopt { listop(@_, "getsockopt") } |
1511 |
sub pp_ssockopt { listop(@_, "setsockopt") } |
1512 |
sub pp_chown { maybe_targmy(@_, \&listop, "chown") } |
1513 |
sub pp_unlink { maybe_targmy(@_, \&listop, "unlink") } |
1514 |
sub pp_chmod { maybe_targmy(@_, \&listop, "chmod") } |
1515 |
sub pp_utime { maybe_targmy(@_, \&listop, "utime") } |
1516 |
sub pp_rename { maybe_targmy(@_, \&listop, "rename") } |
1517 |
sub pp_link { maybe_targmy(@_, \&listop, "link") } |
1518 |
sub pp_symlink { maybe_targmy(@_, \&listop, "symlink") } |
1519 |
sub pp_mkdir { maybe_targmy(@_, \&listop, "mkdir") } |
1520 |
sub pp_open_dir { listop(@_, "opendir") } |
1521 |
sub pp_seekdir { listop(@_, "seekdir") } |
1522 |
sub pp_waitpid { maybe_targmy(@_, \&listop, "waitpid") } |
1523 |
sub pp_system { maybe_targmy(@_, \&listop, "system") } |
1524 |
sub pp_exec { maybe_targmy(@_, \&listop, "exec") } |
1525 |
sub pp_kill { maybe_targmy(@_, \&listop, "kill") } |
1526 |
sub pp_setpgrp { maybe_targmy(@_, \&listop, "setpgrp") } |
1527 |
sub pp_getpriority { maybe_targmy(@_, \&listop, "getpriority") } |
1528 |
sub pp_setpriority { maybe_targmy(@_, \&listop, "setpriority") } |
1529 |
sub pp_shmget { listop(@_, "shmget") } |
1530 |
sub pp_shmctl { listop(@_, "shmctl") } |
1531 |
sub pp_shmread { listop(@_, "shmread") } |
1532 |
sub pp_shmwrite { listop(@_, "shmwrite") } |
1533 |
sub pp_msgget { listop(@_, "msgget") } |
1534 |
sub pp_msgctl { listop(@_, "msgctl") } |
1535 |
sub pp_msgsnd { listop(@_, "msgsnd") } |
1536 |
sub pp_msgrcv { listop(@_, "msgrcv") } |
1537 |
sub pp_semget { listop(@_, "semget") } |
1538 |
sub pp_semctl { listop(@_, "semctl") } |
1539 |
sub pp_semop { listop(@_, "semop") } |
1540 |
sub pp_ghbyaddr { listop(@_, "gethostbyaddr") } |
1541 |
sub pp_gnbyaddr { listop(@_, "getnetbyaddr") } |
1542 |
sub pp_gpbynumber { listop(@_, "getprotobynumber") } |
1543 |
sub pp_gsbyname { listop(@_, "getservbyname") } |
1544 |
sub pp_gsbyport { listop(@_, "getservbyport") } |
1545 |
sub pp_syscall { listop(@_, "syscall") } |
1546 |
|
1547 |
sub pp_glob { |
1548 |
my $self = shift; |
1549 |
my($op, $cx) = @_; |
1550 |
my $text = $self->dq($op->first->sibling); # skip pushmark |
1551 |
if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline |
1552 |
or $text =~ /[<>]/) { |
1553 |
return 'glob(' . single_delim('qq', '"', $text) . ')'; |
1554 |
} else { |
1555 |
return '<' . $text . '>'; |
1556 |
} |
1557 |
} |
1558 |
|
1559 |
# Truncate is special because OPf_SPECIAL makes a bareword first arg |
1560 |
# be a filehandle. This could probably be better fixed in the core |
1561 |
# by moving the GV lookup into ck_truc. |
1562 |
|
1563 |
sub pp_truncate { |
1564 |
my $self = shift; |
1565 |
my($op, $cx) = @_; |
1566 |
my(@exprs); |
1567 |
my $parens = ($cx >= 5) || $self->{'parens'}; |
1568 |
my $kid = $op->first->sibling; |
1569 |
my $fh; |
1570 |
if ($op->flags & OPf_SPECIAL) { |
1571 |
# $kid is an OP_CONST |
1572 |
$fh = $self->const_sv($kid)->PV; |
1573 |
} else { |
1574 |
$fh = $self->deparse($kid, 6); |
1575 |
$fh = "+$fh" if not $parens and substr($fh, 0, 1) eq "("; |
1576 |
} |
1577 |
my $len = $self->deparse($kid->sibling, 6); |
1578 |
if ($parens) { |
1579 |
return "truncate($fh, $len)"; |
1580 |
} else { |
1581 |
return "truncate $fh, $len"; |
1582 |
} |
1583 |
} |
1584 |
|
1585 |
sub indirop { |
1586 |
my $self = shift; |
1587 |
my($op, $cx, $name) = @_; |
1588 |
my($expr, @exprs); |
1589 |
my $kid = $op->first->sibling; |
1590 |
my $indir = ""; |
1591 |
if ($op->flags & OPf_STACKED) { |
1592 |
$indir = $kid; |
1593 |
$indir = $indir->first; # skip rv2gv |
1594 |
if (is_scope($indir)) { |
1595 |
$indir = "{" . $self->deparse($indir, 0) . "}"; |
1596 |
} else { |
1597 |
$indir = $self->deparse($indir, 24); |
1598 |
} |
1599 |
$indir = $indir . " "; |
1600 |
$kid = $kid->sibling; |
1601 |
} |
1602 |
for (; !null($kid); $kid = $kid->sibling) { |
1603 |
$expr = $self->deparse($kid, 6); |
1604 |
push @exprs, $expr; |
1605 |
} |
1606 |
return $self->maybe_parens_func($name, $indir . join(", ", @exprs), |
1607 |
$cx, 5); |
1608 |
} |
1609 |
|
1610 |
sub pp_prtf { indirop(@_, "printf") } |
1611 |
sub pp_print { indirop(@_, "print") } |
1612 |
sub pp_sort { indirop(@_, "sort") } |
1613 |
|
1614 |
sub mapop { |
1615 |
my $self = shift; |
1616 |
my($op, $cx, $name) = @_; |
1617 |
my($expr, @exprs); |
1618 |
my $kid = $op->first; # this is the (map|grep)start |
1619 |
$kid = $kid->first->sibling; # skip a pushmark |
1620 |
my $code = $kid->first; # skip a null |
1621 |
if (is_scope $code) { |
1622 |
$code = "{" . $self->deparse($code, 0) . "} "; |
1623 |
} else { |
1624 |
$code = $self->deparse($code, 24) . ", "; |
1625 |
} |
1626 |
$kid = $kid->sibling; |
1627 |
for (; !null($kid); $kid = $kid->sibling) { |
1628 |
$expr = $self->deparse($kid, 6); |
1629 |
push @exprs, $expr if $expr; |
1630 |
} |
1631 |
return $self->maybe_parens_func($name, $code . join(", ", @exprs), $cx, 5); |
1632 |
} |
1633 |
|
1634 |
sub pp_mapwhile { mapop(@_, "map") } |
1635 |
sub pp_grepwhile { mapop(@_, "grep") } |
1636 |
|
1637 |
sub pp_list { |
1638 |
my $self = shift; |
1639 |
my($op, $cx) = @_; |
1640 |
my($expr, @exprs); |
1641 |
my $kid = $op->first->sibling; # skip pushmark |
1642 |
my $lop; |
1643 |
my $local = "either"; # could be local(...) or my(...) |
1644 |
for ($lop = $kid; !null($lop); $lop = $lop->sibling) { |
1645 |
# This assumes that no other private flags equal 128, and that |
1646 |
# OPs that store things other than flags in their op_private, |
1647 |
# like OP_AELEMFAST, won't be immediate children of a list. |
1648 |
unless ($lop->private & OPpLVAL_INTRO or $lop->name eq "undef") |
1649 |
{ |
1650 |
$local = ""; # or not |
1651 |
last; |
1652 |
} |
1653 |
if ($lop->name =~ /^pad[ash]v$/) { # my() |
1654 |
($local = "", last) if $local eq "local"; |
1655 |
$local = "my"; |
1656 |
} elsif ($lop->name ne "undef") { # local() |
1657 |
($local = "", last) if $local eq "my"; |
1658 |
$local = "local"; |
1659 |
} |
1660 |
} |
1661 |
$local = "" if $local eq "either"; # no point if it's all undefs |
1662 |
return $self->deparse($kid, $cx) if null $kid->sibling and not $local; |
1663 |
for (; !null($kid); $kid = $kid->sibling) { |
1664 |
if ($local) { |
1665 |
if (class($kid) eq "UNOP" and $kid->first->name eq "gvsv") { |
1666 |
$lop = $kid->first; |
1667 |
} else { |
1668 |
$lop = $kid; |
1669 |
} |
1670 |
$self->{'avoid_local'}{$$lop}++; |
1671 |
$expr = $self->deparse($kid, 6); |
1672 |
delete $self->{'avoid_local'}{$$lop}; |
1673 |
} else { |
1674 |
$expr = $self->deparse($kid, 6); |
1675 |
} |
1676 |
push @exprs, $expr; |
1677 |
} |
1678 |
if ($local) { |
1679 |
return "$local(" . join(", ", @exprs) . ")"; |
1680 |
} else { |
1681 |
return $self->maybe_parens( join(", ", @exprs), $cx, 6); |
1682 |
} |
1683 |
} |
1684 |
|
1685 |
sub is_ifelse_cont { |
1686 |
my $op = shift; |
1687 |
return ($op->name eq "null" and class($op) eq "UNOP" |
1688 |
and $op->first->name =~ /^(and|cond_expr)$/ |
1689 |
and is_scope($op->first->first->sibling)); |
1690 |
} |
1691 |
|
1692 |
sub pp_cond_expr { |
1693 |
my $self = shift; |
1694 |
my($op, $cx) = @_; |
1695 |
my $cond = $op->first; |
1696 |
my $true = $cond->sibling; |
1697 |
my $false = $true->sibling; |
1698 |
my $cuddle = $self->{'cuddle'}; |
1699 |
unless ($cx == 0 and (is_scope($true) and $true->name ne "null") and |
1700 |
(is_scope($false) || is_ifelse_cont($false)) |
1701 |
and $self->{'expand'} < 7) { |
1702 |
$cond = $self->deparse($cond, 8); |
1703 |
$true = $self->deparse($true, 8); |
1704 |
$false = $self->deparse($false, 8); |
1705 |
return $self->maybe_parens("$cond ? $true : $false", $cx, 8); |
1706 |
} |
1707 |
|
1708 |
$cond = $self->deparse($cond, 1); |
1709 |
$true = $self->deparse($true, 0); |
1710 |
my $head = "if ($cond) {\n\t$true\n\b}"; |
1711 |
my @elsifs; |
1712 |
while (!null($false) and is_ifelse_cont($false)) { |
1713 |
my $newop = $false->first; |
1714 |
my $newcond = $newop->first; |
1715 |
my $newtrue = $newcond->sibling; |
1716 |
$false = $newtrue->sibling; # last in chain is OP_AND => no else |
1717 |
$newcond = $self->deparse($newcond, 1); |
1718 |
$newtrue = $self->deparse($newtrue, 0); |
1719 |
push @elsifs, "elsif ($newcond) {\n\t$newtrue\n\b}"; |
1720 |
} |
1721 |
if (!null($false)) { |
1722 |
$false = $cuddle . "else {\n\t" . |
1723 |
$self->deparse($false, 0) . "\n\b}\cK"; |
1724 |
} else { |
1725 |
$false = "\cK"; |
1726 |
} |
1727 |
return $head . join($cuddle, "", @elsifs) . $false; |
1728 |
} |
1729 |
|
1730 |
sub loop_common { |
1731 |
my $self = shift; |
1732 |
my($op, $cx, $init) = @_; |
1733 |
my $enter = $op->first; |
1734 |
my $kid = $enter->sibling; |
1735 |
local($self->{'curstash'}) = $self->{'curstash'}; |
1736 |
my $head = ""; |
1737 |
my $bare = 0; |
1738 |
my $body; |
1739 |
my $cond = undef; |
1740 |
if ($kid->name eq "lineseq") { # bare or infinite loop |
1741 |
if (is_state $kid->last) { # infinite |
1742 |
$head = "for (;;) "; # shorter than while (1) |
1743 |
$cond = ""; |
1744 |
} else { |
1745 |
$bare = 1; |
1746 |
} |
1747 |
$body = $kid; |
1748 |
} elsif ($enter->name eq "enteriter") { # foreach |
1749 |
my $ary = $enter->first->sibling; # first was pushmark |
1750 |
my $var = $ary->sibling; |
1751 |
if ($enter->flags & OPf_STACKED |
1752 |
and not null $ary->first->sibling->sibling) |
1753 |
{ |
1754 |
$ary = $self->deparse($ary->first->sibling, 9) . " .. " . |
1755 |
$self->deparse($ary->first->sibling->sibling, 9); |
1756 |
} else { |
1757 |
$ary = $self->deparse($ary, 1); |
1758 |
} |
1759 |
if (null $var) { |
1760 |
if ($enter->flags & OPf_SPECIAL) { # thread special var |
1761 |
$var = $self->pp_threadsv($enter, 1); |
1762 |
} else { # regular my() variable |
1763 |
$var = $self->pp_padsv($enter, 1); |
1764 |
if ($self->padname_sv($enter->targ)->IVX == |
1765 |
$kid->first->first->sibling->last->cop_seq) |
1766 |
{ |
1767 |
# If the scope of this variable closes at the last |
1768 |
# statement of the loop, it must have been |
1769 |
# declared here. |
1770 |
$var = "my " . $var; |
1771 |
} |
1772 |
} |
1773 |
} elsif ($var->name eq "rv2gv") { |
1774 |
$var = $self->pp_rv2sv($var, 1); |
1775 |
} elsif ($var->name eq "gv") { |
1776 |
$var = "\$" . $self->deparse($var, 1); |
1777 |
} |
1778 |
$head = "foreach $var ($ary) "; |
1779 |
$body = $kid->first->first->sibling; # skip OP_AND and OP_ITER |
1780 |
} elsif ($kid->name eq "null") { # while/until |
1781 |
$kid = $kid->first; |
1782 |
my $name = {"and" => "while", "or" => "until"}->{$kid->name}; |
1783 |
$cond = $self->deparse($kid->first, 1); |
1784 |
$head = "$name ($cond) "; |
1785 |
$body = $kid->first->sibling; |
1786 |
} elsif ($kid->name eq "stub") { # bare and empty |
1787 |
return "{;}"; # {} could be a hashref |
1788 |
} |
1789 |
# If there isn't a continue block, then the next pointer for the loop |
1790 |
# will point to the unstack, which is kid's penultimate child, except |
1791 |
# in a bare loop, when it will point to the leaveloop. When neither of |
1792 |
# these conditions hold, then the third-to-last child in the continue |
1793 |
# block (or the last in a bare loop). |
1794 |
my $cont_start = $enter->nextop; |
1795 |
my $cont; |
1796 |
if ($$cont_start != $$op and $ {$cont_start->sibling} != $ {$body->last}) { |
1797 |
if ($bare) { |
1798 |
$cont = $body->last; |
1799 |
} else { |
1800 |
$cont = $body->first; |
1801 |
while (!null($cont->sibling->sibling->sibling)) { |
1802 |
$cont = $cont->sibling; |
1803 |
} |
1804 |
} |
1805 |
my $state = $body->first; |
1806 |
my $cuddle = $self->{'cuddle'}; |
1807 |
my @states; |
1808 |
for (; $$state != $$cont; $state = $state->sibling) { |
1809 |
push @states, $state; |
1810 |
} |
1811 |
$body = $self->lineseq(@states); |
1812 |
if (defined $cond and not is_scope $cont and $self->{'expand'} < 3) { |
1813 |
$head = "for ($init; $cond; " . $self->deparse($cont, 1) .") "; |
1814 |
$cont = "\cK"; |
1815 |
} else { |
1816 |
$cont = $cuddle . "continue {\n\t" . |
1817 |
$self->deparse($cont, 0) . "\n\b}\cK"; |
1818 |
} |
1819 |
} else { |
1820 |
$cont = "\cK"; |
1821 |
$body = $self->deparse($body, 0); |
1822 |
} |
1823 |
return $head . "{\n\t" . $body . "\n\b}" . $cont; |
1824 |
} |
1825 |
|
1826 |
sub pp_leaveloop { loop_common(@_, "") } |
1827 |
|
1828 |
sub for_loop { |
1829 |
my $self = shift; |
1830 |
my($op, $cx) = @_; |
1831 |
my $init = $self->deparse($op, 1); |
1832 |
return $self->loop_common($op->sibling, $cx, $init); |
1833 |
} |
1834 |
|
1835 |
sub pp_leavetry { |
1836 |
my $self = shift; |
1837 |
return "eval {\n\t" . $self->pp_leave(@_) . "\n\b}"; |
1838 |
} |
1839 |
|
1840 |
BEGIN { eval "sub OP_CONST () {" . opnumber("const") . "}" } |
1841 |
BEGIN { eval "sub OP_STRINGIFY () {" . opnumber("stringify") . "}" } |
1842 |
|
1843 |
sub pp_null { |
1844 |
my $self = shift; |
1845 |
my($op, $cx) = @_; |
1846 |
if (class($op) eq "OP") { |
1847 |
# old value is lost |
1848 |
return $self->{'ex_const'} if $op->targ == OP_CONST; |
1849 |
} elsif ($op->first->name eq "pushmark") { |
1850 |
return $self->pp_list($op, $cx); |
1851 |
} elsif ($op->first->name eq "enter") { |
1852 |
return $self->pp_leave($op, $cx); |
1853 |
} elsif ($op->targ == OP_STRINGIFY) { |
1854 |
return $self->dquote($op, $cx); |
1855 |
} elsif (!null($op->first->sibling) and |
1856 |
$op->first->sibling->name eq "readline" and |
1857 |
$op->first->sibling->flags & OPf_STACKED) { |
1858 |
return $self->maybe_parens($self->deparse($op->first, 7) . " = " |
1859 |
. $self->deparse($op->first->sibling, 7), |
1860 |
$cx, 7); |
1861 |
} elsif (!null($op->first->sibling) and |
1862 |
$op->first->sibling->name eq "trans" and |
1863 |
$op->first->sibling->flags & OPf_STACKED) { |
1864 |
return $self->maybe_parens($self->deparse($op->first, 20) . " =~ " |
1865 |
. $self->deparse($op->first->sibling, 20), |
1866 |
$cx, 20); |
1867 |
} else { |
1868 |
return $self->deparse($op->first, $cx); |
1869 |
} |
1870 |
} |
1871 |
|
1872 |
sub padname { |
1873 |
my $self = shift; |
1874 |
my $targ = shift; |
1875 |
return $self->padname_sv($targ)->PVX; |
1876 |
} |
1877 |
|
1878 |
sub padany { |
1879 |
my $self = shift; |
1880 |
my $op = shift; |
1881 |
return substr($self->padname($op->targ), 1); # skip $/@/% |
1882 |
} |
1883 |
|
1884 |
sub pp_padsv { |
1885 |
my $self = shift; |
1886 |
my($op, $cx) = @_; |
1887 |
return $self->maybe_my($op, $cx, $self->padname($op->targ)); |
1888 |
} |
1889 |
|
1890 |
sub pp_padav { pp_padsv(@_) } |
1891 |
sub pp_padhv { pp_padsv(@_) } |
1892 |
|
1893 |
my @threadsv_names; |
1894 |
|
1895 |
BEGIN { |
1896 |
@threadsv_names = ("_", "1", "2", "3", "4", "5", "6", "7", "8", "9", |
1897 |
"&", "`", "'", "+", "/", ".", ",", "\\", '"', ";", |
1898 |
"^", "-", "%", "=", "|", "~", ":", "^A", "^E", |
1899 |
"!", "@"); |
1900 |
} |
1901 |
|
1902 |
sub pp_threadsv { |
1903 |
my $self = shift; |
1904 |
my($op, $cx) = @_; |
1905 |
return $self->maybe_local($op, $cx, "\$" . $threadsv_names[$op->targ]); |
1906 |
} |
1907 |
|
1908 |
sub gv_or_padgv { |
1909 |
my $self = shift; |
1910 |
my $op = shift; |
1911 |
if (class($op) eq "PADOP") { |
1912 |
return $self->padval($op->padix); |
1913 |
} else { # class($op) eq "SVOP" |
1914 |
return $op->gv; |
1915 |
} |
1916 |
} |
1917 |
|
1918 |
sub pp_gvsv { |
1919 |
my $self = shift; |
1920 |
my($op, $cx) = @_; |
1921 |
my $gv = $self->gv_or_padgv($op); |
1922 |
return $self->maybe_local($op, $cx, "\$" . $self->gv_name($gv)); |
1923 |
} |
1924 |
|
1925 |
sub pp_gv { |
1926 |
my $self = shift; |
1927 |
my($op, $cx) = @_; |
1928 |
my $gv = $self->gv_or_padgv($op); |
1929 |
return $self->gv_name($gv); |
1930 |
} |
1931 |
|
1932 |
sub pp_aelemfast { |
1933 |
my $self = shift; |
1934 |
my($op, $cx) = @_; |
1935 |
my $gv = $self->gv_or_padgv($op); |
1936 |
return "\$" . $self->gv_name($gv) . "[" . $op->private . "]"; |
1937 |
} |
1938 |
|
1939 |
sub rv2x { |
1940 |
my $self = shift; |
1941 |
my($op, $cx, $type) = @_; |
1942 |
my $kid = $op->first; |
1943 |
my $str = $self->deparse($kid, 0); |
1944 |
return $type . (is_scalar($kid) ? $str : "{$str}"); |
1945 |
} |
1946 |
|
1947 |
sub pp_rv2sv { maybe_local(@_, rv2x(@_, "\$")) } |
1948 |
sub pp_rv2hv { maybe_local(@_, rv2x(@_, "%")) } |
1949 |
sub pp_rv2gv { maybe_local(@_, rv2x(@_, "*")) } |
1950 |
|
1951 |
# skip rv2av |
1952 |
sub pp_av2arylen { |
1953 |
my $self = shift; |
1954 |
my($op, $cx) = @_; |
1955 |
if ($op->first->name eq "padav") { |
1956 |
return $self->maybe_local($op, $cx, '$#' . $self->padany($op->first)); |
1957 |
} else { |
1958 |
return $self->maybe_local($op, $cx, |
1959 |
$self->rv2x($op->first, $cx, '$#')); |
1960 |
} |
1961 |
} |
1962 |
|
1963 |
# skip down to the old, ex-rv2cv |
1964 |
sub pp_rv2cv { $_[0]->rv2x($_[1]->first->first->sibling, $_[2], "&") } |
1965 |
|
1966 |
sub pp_rv2av { |
1967 |
my $self = shift; |
1968 |
my($op, $cx) = @_; |
1969 |
my $kid = $op->first; |
1970 |
if ($kid->name eq "const") { # constant list |
1971 |
my $av = $self->const_sv($kid); |
1972 |
return "(" . join(", ", map(const($_), $av->ARRAY)) . ")"; |
1973 |
} else { |
1974 |
return $self->maybe_local($op, $cx, $self->rv2x($op, $cx, "\@")); |
1975 |
} |
1976 |
} |
1977 |
|
1978 |
sub is_subscriptable { |
1979 |
my $op = shift; |
1980 |
if ($op->name =~ /^[ahg]elem/) { |
1981 |
return 1; |
1982 |
} elsif ($op->name eq "entersub") { |
1983 |
my $kid = $op->first; |
1984 |
return 0 unless null $kid->sibling; |
1985 |
$kid = $kid->first; |
1986 |
$kid = $kid->sibling until null $kid->sibling; |
1987 |
return 0 if is_scope($kid); |
1988 |
$kid = $kid->first; |
1989 |
return 0 if $kid->name eq "gv"; |
1990 |
return 0 if is_scalar($kid); |
1991 |
return is_subscriptable($kid); |
1992 |
} else { |
1993 |
return 0; |
1994 |
} |
1995 |
} |
1996 |
|
1997 |
sub elem { |
1998 |
my $self = shift; |
1999 |
my ($op, $cx, $left, $right, $padname) = @_; |
2000 |
my($array, $idx) = ($op->first, $op->first->sibling); |
2001 |
unless ($array->name eq $padname) { # Maybe this has been fixed |
2002 |
$array = $array->first; # skip rv2av (or ex-rv2av in _53+) |
2003 |
} |
2004 |
if ($array->name eq $padname) { |
2005 |
$array = $self->padany($array); |
2006 |
} elsif (is_scope($array)) { # ${expr}[0] |
2007 |
$array = "{" . $self->deparse($array, 0) . "}"; |
2008 |
} elsif (is_scalar $array) { # $x[0], $$x[0], ... |
2009 |
$array = $self->deparse($array, 24); |
2010 |
} else { |
2011 |
# $x[20][3]{hi} or expr->[20] |
2012 |
my $arrow = is_subscriptable($array) ? "" : "->"; |
2013 |
return $self->deparse($array, 24) . $arrow . |
2014 |
$left . $self->deparse($idx, 1) . $right; |
2015 |
} |
2016 |
$idx = $self->deparse($idx, 1); |
2017 |
return "\$" . $array . $left . $idx . $right; |
2018 |
} |
2019 |
|
2020 |
sub pp_aelem { maybe_local(@_, elem(@_, "[", "]", "padav")) } |
2021 |
sub pp_helem { maybe_local(@_, elem(@_, "{", "}", "padhv")) } |
2022 |
|
2023 |
sub pp_gelem { |
2024 |
my $self = shift; |
2025 |
my($op, $cx) = @_; |
2026 |
my($glob, $part) = ($op->first, $op->last); |
2027 |
$glob = $glob->first; # skip rv2gv |
2028 |
$glob = $glob->first if $glob->name eq "rv2gv"; # this one's a bug |
2029 |
my $scope = is_scope($glob); |
2030 |
$glob = $self->deparse($glob, 0); |
2031 |
$part = $self->deparse($part, 1); |
2032 |
return "*" . ($scope ? "{$glob}" : $glob) . "{$part}"; |
2033 |
} |
2034 |
|
2035 |
sub slice { |
2036 |
my $self = shift; |
2037 |
my ($op, $cx, $left, $right, $regname, $padname) = @_; |
2038 |
my $last; |
2039 |
my(@elems, $kid, $array, $list); |
2040 |
if (class($op) eq "LISTOP") { |
2041 |
$last = $op->last; |
2042 |
} else { # ex-hslice inside delete() |
2043 |
for ($kid = $op->first; !null $kid->sibling; $kid = $kid->sibling) {} |
2044 |
$last = $kid; |
2045 |
} |
2046 |
$array = $last; |
2047 |
$array = $array->first |
2048 |
if $array->name eq $regname or $array->name eq "null"; |
2049 |
if (is_scope($array)) { |
2050 |
$array = "{" . $self->deparse($array, 0) . "}"; |
2051 |
} elsif ($array->name eq $padname) { |
2052 |
$array = $self->padany($array); |
2053 |
} else { |
2054 |
$array = $self->deparse($array, 24); |
2055 |
} |
2056 |
$kid = $op->first->sibling; # skip pushmark |
2057 |
if ($kid->name eq "list") { |
2058 |
$kid = $kid->first->sibling; # skip list, pushmark |
2059 |
for (; !null $kid; $kid = $kid->sibling) { |
2060 |
push @elems, $self->deparse($kid, 6); |
2061 |
} |
2062 |
$list = join(", ", @elems); |
2063 |
} else { |
2064 |
$list = $self->deparse($kid, 1); |
2065 |
} |
2066 |
return "\@" . $array . $left . $list . $right; |
2067 |
} |
2068 |
|
2069 |
sub pp_aslice { maybe_local(@_, slice(@_, "[", "]", "rv2av", "padav")) } |
2070 |
sub pp_hslice { maybe_local(@_, slice(@_, "{", "}", "rv2hv", "padhv")) } |
2071 |
|
2072 |
sub pp_lslice { |
2073 |
my $self = shift; |
2074 |
my($op, $cx) = @_; |
2075 |
my $idx = $op->first; |
2076 |
my $list = $op->last; |
2077 |
my(@elems, $kid); |
2078 |
$list = $self->deparse($list, 1); |
2079 |
$idx = $self->deparse($idx, 1); |
2080 |
return "($list)" . "[$idx]"; |
2081 |
} |
2082 |
|
2083 |
sub want_scalar { |
2084 |
my $op = shift; |
2085 |
return ($op->flags & OPf_WANT) == OPf_WANT_SCALAR; |
2086 |
} |
2087 |
|
2088 |
sub want_list { |
2089 |
my $op = shift; |
2090 |
return ($op->flags & OPf_WANT) == OPf_WANT_LIST; |
2091 |
} |
2092 |
|
2093 |
sub method { |
2094 |
my $self = shift; |
2095 |
my($op, $cx) = @_; |
2096 |
my $kid = $op->first->sibling; # skip pushmark |
2097 |
my($meth, $obj, @exprs); |
2098 |
if ($kid->name eq "list" and want_list $kid) { |
2099 |
# When an indirect object isn't a bareword but the args are in |
2100 |
# parens, the parens aren't part of the method syntax (the LLAFR |
2101 |
# doesn't apply), but they make a list with OPf_PARENS set that |
2102 |
# doesn't get flattened by the append_elem that adds the method, |
2103 |
# making a (object, arg1, arg2, ...) list where the object |
2104 |
# usually is. This can be distinguished from |
2105 |
# `($obj, $arg1, $arg2)->meth()' (which is legal if $arg2 is an |
2106 |
# object) because in the later the list is in scalar context |
2107 |
# as the left side of -> always is, while in the former |
2108 |
# the list is in list context as method arguments always are. |
2109 |
# (Good thing there aren't method prototypes!) |
2110 |
$meth = $kid->sibling; |
2111 |
$kid = $kid->first->sibling; # skip pushmark |
2112 |
$obj = $kid; |
2113 |
$kid = $kid->sibling; |
2114 |
for (; not null $kid; $kid = $kid->sibling) { |
2115 |
push @exprs, $self->deparse($kid, 6); |
2116 |
} |
2117 |
} else { |
2118 |
$obj = $kid; |
2119 |
$kid = $kid->sibling; |
2120 |
for (; not null $kid->sibling; $kid = $kid->sibling) { |
2121 |
push @exprs, $self->deparse($kid, 6); |
2122 |
} |
2123 |
$meth = $kid; |
2124 |
} |
2125 |
$obj = $self->deparse($obj, 24); |
2126 |
if ($meth->name eq "method_named") { |
2127 |
$meth = $self->const_sv($meth)->PV; |
2128 |
} else { |
2129 |
$meth = $meth->first; |
2130 |
if ($meth->name eq "const") { |
2131 |
# As of 5.005_58, this case is probably obsoleted by the |
2132 |
# method_named case above |
2133 |
$meth = $self->const_sv($meth)->PV; # needs to be bare |
2134 |
} else { |
2135 |
$meth = $self->deparse($meth, 1); |
2136 |
} |
2137 |
} |
2138 |
my $args = join(", ", @exprs); |
2139 |
$kid = $obj . "->" . $meth; |
2140 |
if ($args) { |
2141 |
return $kid . "(" . $args . ")"; # parens mandatory |
2142 |
} else { |
2143 |
return $kid; |
2144 |
} |
2145 |
} |
2146 |
|
2147 |
# returns "&" if the prototype doesn't match the args, |
2148 |
# or ("", $args_after_prototype_demunging) if it does. |
2149 |
sub check_proto { |
2150 |
my $self = shift; |
2151 |
my($proto, @args) = @_; |
2152 |
my($arg, $real); |
2153 |
my $doneok = 0; |
2154 |
my @reals; |
2155 |
# An unbackslashed @ or % gobbles up the rest of the args |
2156 |
$proto =~ s/([^\\]|^)([@%])(.*)$/$1$2/; |
2157 |
while ($proto) { |
2158 |
$proto =~ s/^ *([\\]?[\$\@&%*]|;)//; |
2159 |
my $chr = $1; |
2160 |
if ($chr eq "") { |
2161 |
return "&" if @args; |
2162 |
} elsif ($chr eq ";") { |
2163 |
$doneok = 1; |
2164 |
} elsif ($chr eq "@" or $chr eq "%") { |
2165 |
push @reals, map($self->deparse($_, 6), @args); |
2166 |
@args = (); |
2167 |
} else { |
2168 |
$arg = shift @args; |
2169 |
last unless $arg; |
2170 |
if ($chr eq "\$") { |
2171 |
if (want_scalar $arg) { |
2172 |
push @reals, $self->deparse($arg, 6); |
2173 |
} else { |
2174 |
return "&"; |
2175 |
} |
2176 |
} elsif ($chr eq "&") { |
2177 |
if ($arg->name =~ /^(s?refgen|undef)$/) { |
2178 |
push @reals, $self->deparse($arg, 6); |
2179 |
} else { |
2180 |
return "&"; |
2181 |
} |
2182 |
} elsif ($chr eq "*") { |
2183 |
if ($arg->name =~ /^s?refgen$/ |
2184 |
and $arg->first->first->name eq "rv2gv") |
2185 |
{ |
2186 |
$real = $arg->first->first; # skip refgen, null |
2187 |
if ($real->first->name eq "gv") { |
2188 |
push @reals, $self->deparse($real, 6); |
2189 |
} else { |
2190 |
push @reals, $self->deparse($real->first, 6); |
2191 |
} |
2192 |
} else { |
2193 |
return "&"; |
2194 |
} |
2195 |
} elsif (substr($chr, 0, 1) eq "\\") { |
2196 |
$chr = substr($chr, 1); |
2197 |
if ($arg->name =~ /^s?refgen$/ and |
2198 |
!null($real = $arg->first) and |
2199 |
($chr eq "\$" && is_scalar($real->first) |
2200 |
or ($chr eq "\@" |
2201 |
&& $real->first->sibling->name |
2202 |
=~ /^(rv2|pad)av$/) |
2203 |
or ($chr eq "%" |
2204 |
&& $real->first->sibling->name |
2205 |
=~ /^(rv2|pad)hv$/) |
2206 |
#or ($chr eq "&" # This doesn't work |
2207 |
# && $real->first->name eq "rv2cv") |
2208 |
or ($chr eq "*" |
2209 |
&& $real->first->name eq "rv2gv"))) |
2210 |
{ |
2211 |
push @reals, $self->deparse($real, 6); |
2212 |
} else { |
2213 |
return "&"; |
2214 |
} |
2215 |
} |
2216 |
} |
2217 |
} |
2218 |
return "&" if $proto and !$doneok; # too few args and no `;' |
2219 |
return "&" if @args; # too many args |
2220 |
return ("", join ", ", @reals); |
2221 |
} |
2222 |
|
2223 |
sub pp_entersub { |
2224 |
my $self = shift; |
2225 |
my($op, $cx) = @_; |
2226 |
return $self->method($op, $cx) unless null $op->first->sibling; |
2227 |
my $prefix = ""; |
2228 |
my $amper = ""; |
2229 |
my($kid, @exprs); |
2230 |
if ($op->flags & OPf_SPECIAL) { |
2231 |
$prefix = "do "; |
2232 |
} elsif ($op->private & OPpENTERSUB_AMPER) { |
2233 |
$amper = "&"; |
2234 |
} |
2235 |
$kid = $op->first; |
2236 |
$kid = $kid->first->sibling; # skip ex-list, pushmark |
2237 |
for (; not null $kid->sibling; $kid = $kid->sibling) { |
2238 |
push @exprs, $kid; |
2239 |
} |
2240 |
my $simple = 0; |
2241 |
my $proto = undef; |
2242 |
if (is_scope($kid)) { |
2243 |
$amper = "&"; |
2244 |
$kid = "{" . $self->deparse($kid, 0) . "}"; |
2245 |
} elsif ($kid->first->name eq "gv") { |
2246 |
my $gv = $self->gv_or_padgv($kid->first); |
2247 |
if (class($gv->CV) ne "SPECIAL") { |
2248 |
$proto = $gv->CV->PV if $gv->CV->FLAGS & SVf_POK; |
2249 |
} |
2250 |
$simple = 1; # only calls of named functions can be prototyped |
2251 |
$kid = $self->deparse($kid, 24); |
2252 |
} elsif (is_scalar $kid->first) { |
2253 |
$amper = "&"; |
2254 |
$kid = $self->deparse($kid, 24); |
2255 |
} else { |
2256 |
$prefix = ""; |
2257 |
my $arrow = is_subscriptable($kid->first) ? "" : "->"; |
2258 |
$kid = $self->deparse($kid, 24) . $arrow; |
2259 |
} |
2260 |
my $args; |
2261 |
if (defined $proto and not $amper) { |
2262 |
($amper, $args) = $self->check_proto($proto, @exprs); |
2263 |
if ($amper eq "&") { |
2264 |
$args = join(", ", map($self->deparse($_, 6), @exprs)); |
2265 |
} |
2266 |
} else { |
2267 |
$args = join(", ", map($self->deparse($_, 6), @exprs)); |
2268 |
} |
2269 |
if ($prefix or $amper) { |
2270 |
if ($op->flags & OPf_STACKED) { |
2271 |
return $prefix . $amper . $kid . "(" . $args . ")"; |
2272 |
} else { |
2273 |
return $prefix . $amper. $kid; |
2274 |
} |
2275 |
} else { |
2276 |
if (defined $proto and $proto eq "") { |
2277 |
return $kid; |
2278 |
} elsif (defined $proto and $proto eq "\$") { |
2279 |
return $self->maybe_parens_func($kid, $args, $cx, 16); |
2280 |
} elsif (defined($proto) && $proto or $simple) { |
2281 |
return $self->maybe_parens_func($kid, $args, $cx, 5); |
2282 |
} else { |
2283 |
return "$kid(" . $args . ")"; |
2284 |
} |
2285 |
} |
2286 |
} |
2287 |
|
2288 |
sub pp_enterwrite { unop(@_, "write") } |
2289 |
|
2290 |
# escape things that cause interpolation in double quotes, |
2291 |
# but not character escapes |
2292 |
sub uninterp { |
2293 |
my($str) = @_; |
2294 |
$str =~ s/(^|[^\\])([\$\@]|\\[uUlLQE])/$1\\$2/g; |
2295 |
return $str; |
2296 |
} |
2297 |
|
2298 |
# the same, but treat $|, $), and $ at the end of the string differently |
2299 |
sub re_uninterp { |
2300 |
my($str) = @_; |
2301 |
$str =~ s/(^|[^\\])(\@|\\[uUlLQE])/$1\\$2/g; |
2302 |
$str =~ s/(^|[^\\])(\$[^)|])/$1\\$2/g; |
2303 |
return $str; |
2304 |
} |
2305 |
|
2306 |
# character escapes, but not delimiters that might need to be escaped |
2307 |
sub escape_str { # ASCII |
2308 |
my($str) = @_; |
2309 |
$str =~ s/\a/\\a/g; |
2310 |
# $str =~ s/\cH/\\b/g; # \b means someting different in a regex |
2311 |
$str =~ s/\t/\\t/g; |
2312 |
$str =~ s/\n/\\n/g; |
2313 |
$str =~ s/\e/\\e/g; |
2314 |
$str =~ s/\f/\\f/g; |
2315 |
$str =~ s/\r/\\r/g; |
2316 |
$str =~ s/([\cA-\cZ])/'\\c' . chr(ord('@') + ord($1))/ge; |
2317 |
$str =~ s/([\0\033-\037\177-\377])/'\\' . sprintf("%03o", ord($1))/ge; |
2318 |
return $str; |
2319 |
} |
2320 |
|
2321 |
# Don't do this for regexen |
2322 |
sub unback { |
2323 |
my($str) = @_; |
2324 |
$str =~ s/\\/\\\\/g; |
2325 |
return $str; |
2326 |
} |
2327 |
|
2328 |
sub balanced_delim { |
2329 |
my($str) = @_; |
2330 |
my @str = split //, $str; |
2331 |
my($ar, $open, $close, $fail, $c, $cnt); |
2332 |
for $ar (['[',']'], ['(',')'], ['<','>'], ['{','}']) { |
2333 |
($open, $close) = @$ar; |
2334 |
$fail = 0; $cnt = 0; |
2335 |
for $c (@str) { |
2336 |
if ($c eq $open) { |
2337 |
$cnt++; |
2338 |
} elsif ($c eq $close) { |
2339 |
$cnt--; |
2340 |
if ($cnt < 0) { |
2341 |
# qq()() isn't ")(" |
2342 |
$fail = 1; |
2343 |
last; |
2344 |
} |
2345 |
} |
2346 |
} |
2347 |
$fail = 1 if $cnt != 0; |
2348 |
return ($open, "$open$str$close") if not $fail; |
2349 |
} |
2350 |
return ("", $str); |
2351 |
} |
2352 |
|
2353 |
sub single_delim { |
2354 |
my($q, $default, $str) = @_; |
2355 |
return "$default$str$default" if $default and index($str, $default) == -1; |
2356 |
my($succeed, $delim); |
2357 |
($succeed, $str) = balanced_delim($str); |
2358 |
return "$q$str" if $succeed; |
2359 |
for $delim ('/', '"', '#') { |
2360 |
return "$q$delim" . $str . $delim if index($str, $delim) == -1; |
2361 |
} |
2362 |
if ($default) { |
2363 |
$str =~ s/$default/\\$default/g; |
2364 |
return "$default$str$default"; |
2365 |
} else { |
2366 |
$str =~ s[/][\\/]g; |
2367 |
return "$q/$str/"; |
2368 |
} |
2369 |
} |
2370 |
|
2371 |
sub const { |
2372 |
my $sv = shift; |
2373 |
if (class($sv) eq "SPECIAL") { |
2374 |
return ('undef', '1', '0')[$$sv-1]; # sv_undef, sv_yes, sv_no |
2375 |
} elsif ($sv->FLAGS & SVf_IOK) { |
2376 |
return $sv->int_value; |
2377 |
} elsif ($sv->FLAGS & SVf_NOK) { |
2378 |
return $sv->NV; |
2379 |
} elsif ($sv->FLAGS & SVf_ROK) { |
2380 |
return "\\(" . const($sv->RV) . ")"; # constant folded |
2381 |
} else { |
2382 |
my $str = $sv->PV; |
2383 |
if ($str =~ /[^ -~]/) { # ASCII for non-printing |
2384 |
return single_delim("qq", '"', uninterp escape_str unback $str); |
2385 |
} else { |
2386 |
return single_delim("q", "'", unback $str); |
2387 |
} |
2388 |
} |
2389 |
} |
2390 |
|
2391 |
sub const_sv { |
2392 |
my $self = shift; |
2393 |
my $op = shift; |
2394 |
my $sv = $op->sv; |
2395 |
# the constant could be in the pad (under useithreads) |
2396 |
$sv = $self->padval($op->targ) unless $$sv; |
2397 |
return $sv; |
2398 |
} |
2399 |
|
2400 |
sub pp_const { |
2401 |
my $self = shift; |
2402 |
my($op, $cx) = @_; |
2403 |
# if ($op->private & OPpCONST_BARE) { # trouble with `=>' autoquoting |
2404 |
# return $self->const_sv($op)->PV; |
2405 |
# } |
2406 |
my $sv = $self->const_sv($op); |
2407 |
# return const($sv); |
2408 |
my $c = const $sv; |
2409 |
return $c =~ /^-\d/ ? $self->maybe_parens($c, $cx, 21) : $c; |
2410 |
} |
2411 |
|
2412 |
sub dq { |
2413 |
my $self = shift; |
2414 |
my $op = shift; |
2415 |
my $type = $op->name; |
2416 |
if ($type eq "const") { |
2417 |
return uninterp(escape_str(unback($self->const_sv($op)->PV))); |
2418 |
} elsif ($type eq "concat") { |
2419 |
my $first = $self->dq($op->first); |
2420 |
my $last = $self->dq($op->last); |
2421 |
# Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]" |
2422 |
if ($last =~ /^[{\[\w]/) { |
2423 |
$first =~ s/([%\$@])([A-Za-z_]\w*)$/${1}{$2}/; |
2424 |
} |
2425 |
return $first . $last; |
2426 |
} elsif ($type eq "uc") { |
2427 |
return '\U' . $self->dq($op->first->sibling) . '\E'; |
2428 |
} elsif ($type eq "lc") { |
2429 |
return '\L' . $self->dq($op->first->sibling) . '\E'; |
2430 |
} elsif ($type eq "ucfirst") { |
2431 |
return '\u' . $self->dq($op->first->sibling); |
2432 |
} elsif ($type eq "lcfirst") { |
2433 |
return '\l' . $self->dq($op->first->sibling); |
2434 |
} elsif ($type eq "quotemeta") { |
2435 |
return '\Q' . $self->dq($op->first->sibling) . '\E'; |
2436 |
} elsif ($type eq "join") { |
2437 |
return $self->deparse($op->last, 26); # was join($", @ary) |
2438 |
} else { |
2439 |
return $self->deparse($op, 26); |
2440 |
} |
2441 |
} |
2442 |
|
2443 |
sub pp_backtick { |
2444 |
my $self = shift; |
2445 |
my($op, $cx) = @_; |
2446 |
# skip pushmark |
2447 |
return single_delim("qx", '`', $self->dq($op->first->sibling)); |
2448 |
} |
2449 |
|
2450 |
sub dquote { |
2451 |
my $self = shift; |
2452 |
my($op, $cx) = @_; |
2453 |
my $kid = $op->first->sibling; # skip ex-stringify, pushmark |
2454 |
return $self->deparse($kid, $cx) if $self->{'unquote'}; |
2455 |
$self->maybe_targmy($kid, $cx, |
2456 |
sub {single_delim("qq", '"', $self->dq($_[1]))}); |
2457 |
} |
2458 |
|
2459 |
# OP_STRINGIFY is a listop, but it only ever has one arg |
2460 |
sub pp_stringify { maybe_targmy(@_, \&dquote) } |
2461 |
|
2462 |
# tr/// and s/// (and tr[][], tr[]//, tr###, etc) |
2463 |
# note that tr(from)/to/ is OK, but not tr/from/(to) |
2464 |
sub double_delim { |
2465 |
my($from, $to) = @_; |
2466 |
my($succeed, $delim); |
2467 |
if ($from !~ m[/] and $to !~ m[/]) { |
2468 |
return "/$from/$to/"; |
2469 |
} elsif (($succeed, $from) = balanced_delim($from) and $succeed) { |
2470 |
if (($succeed, $to) = balanced_delim($to) and $succeed) { |
2471 |
return "$from$to"; |
2472 |
} else { |
2473 |
for $delim ('/', '"', '#') { # note no `'' -- s''' is special |
2474 |
return "$from$delim$to$delim" if index($to, $delim) == -1; |
2475 |
} |
2476 |
$to =~ s[/][\\/]g; |
2477 |
return "$from/$to/"; |
2478 |
} |
2479 |
} else { |
2480 |
for $delim ('/', '"', '#') { # note no ' |
2481 |
return "$delim$from$delim$to$delim" |
2482 |
if index($to . $from, $delim) == -1; |
2483 |
} |
2484 |
$from =~ s[/][\\/]g; |
2485 |
$to =~ s[/][\\/]g; |
2486 |
return "/$from/$to/"; |
2487 |
} |
2488 |
} |
2489 |
|
2490 |
sub pchr { # ASCII |
2491 |
my($n) = @_; |
2492 |
if ($n == ord '\\') { |
2493 |
return '\\\\'; |
2494 |
} elsif ($n >= ord(' ') and $n <= ord('~')) { |
2495 |
return chr($n); |
2496 |
} elsif ($n == ord "\a") { |
2497 |
return '\\a'; |
2498 |
} elsif ($n == ord "\b") { |
2499 |
return '\\b'; |
2500 |
} elsif ($n == ord "\t") { |
2501 |
return '\\t'; |
2502 |
} elsif ($n == ord "\n") { |
2503 |
return '\\n'; |
2504 |
} elsif ($n == ord "\e") { |
2505 |
return '\\e'; |
2506 |
} elsif ($n == ord "\f") { |
2507 |
return '\\f'; |
2508 |
} elsif ($n == ord "\r") { |
2509 |
return '\\r'; |
2510 |
} elsif ($n >= ord("\cA") and $n <= ord("\cZ")) { |
2511 |
return '\\c' . chr(ord("@") + $n); |
2512 |
} else { |
2513 |
# return '\x' . sprintf("%02x", $n); |
2514 |
return '\\' . sprintf("%03o", $n); |
2515 |
} |
2516 |
} |
2517 |
|
2518 |
sub collapse { |
2519 |
my(@chars) = @_; |
2520 |
my($str, $c, $tr) = (""); |
2521 |
for ($c = 0; $c < @chars; $c++) { |
2522 |
$tr = $chars[$c]; |
2523 |
$str .= pchr($tr); |
2524 |
if ($c <= $#chars - 2 and $chars[$c + 1] == $tr + 1 and |
2525 |
$chars[$c + 2] == $tr + 2) |
2526 |
{ |
2527 |
for (; $c <= $#chars-1 and $chars[$c + 1] == $chars[$c] + 1; $c++) |
2528 |
{} |
2529 |
$str .= "-"; |
2530 |
$str .= pchr($chars[$c]); |
2531 |
} |
2532 |
} |
2533 |
return $str; |
2534 |
} |
2535 |
|
2536 |
# XXX This has trouble with hyphens in the replacement (tr/bac/-AC/), |
2537 |
# and backslashes. |
2538 |
|
2539 |
sub tr_decode_byte { |
2540 |
my($table, $flags) = @_; |
2541 |
my(@table) = unpack("s256", $table); |
2542 |
my($c, $tr, @from, @to, @delfrom, $delhyphen); |
2543 |
if ($table[ord "-"] != -1 and |
2544 |
$table[ord("-") - 1] == -1 || $table[ord("-") + 1] == -1) |
2545 |
{ |
2546 |
$tr = $table[ord "-"]; |
2547 |
$table[ord "-"] = -1; |
2548 |
if ($tr >= 0) { |
2549 |
@from = ord("-"); |
2550 |
@to = $tr; |
2551 |
} else { # -2 ==> delete |
2552 |
$delhyphen = 1; |
2553 |
} |
2554 |
} |
2555 |
for ($c = 0; $c < 256; $c++) { |
2556 |
$tr = $table[$c]; |
2557 |
if ($tr >= 0) { |
2558 |
push @from, $c; push @to, $tr; |
2559 |
} elsif ($tr == -2) { |
2560 |
push @delfrom, $c; |
2561 |
} |
2562 |
} |
2563 |
@from = (@from, @delfrom); |
2564 |
if ($flags & OPpTRANS_COMPLEMENT) { |
2565 |
my @newfrom = (); |
2566 |
my %from; |
2567 |
@from{@from} = (1) x @from; |
2568 |
for ($c = 0; $c < 256; $c++) { |
2569 |
push @newfrom, $c unless $from{$c}; |
2570 |
} |
2571 |
@from = @newfrom; |
2572 |
} |
2573 |
unless ($flags & OPpTRANS_DELETE || !@to) { |
2574 |
pop @to while $#to and $to[$#to] == $to[$#to -1]; |
2575 |
} |
2576 |
my($from, $to); |
2577 |
$from = collapse(@from); |
2578 |
$to = collapse(@to); |
2579 |
$from .= "-" if $delhyphen; |
2580 |
return ($from, $to); |
2581 |
} |
2582 |
|
2583 |
sub tr_chr { |
2584 |
my $x = shift; |
2585 |
if ($x == ord "-") { |
2586 |
return "\\-"; |
2587 |
} else { |
2588 |
return chr $x; |
2589 |
} |
2590 |
} |
2591 |
|
2592 |
# XXX This doesn't yet handle all cases correctly either |
2593 |
|
2594 |
sub tr_decode_utf8 { |
2595 |
my($swash_hv, $flags) = @_; |
2596 |
my %swash = $swash_hv->ARRAY; |
2597 |
my $final = undef; |
2598 |
$final = $swash{'FINAL'}->IV if exists $swash{'FINAL'}; |
2599 |
my $none = $swash{"NONE"}->IV; |
2600 |
my $extra = $none + 1; |
2601 |
my(@from, @delfrom, @to); |
2602 |
my $line; |
2603 |
foreach $line (split /\n/, $swash{'LIST'}->PV) { |
2604 |
my($min, $max, $result) = split(/\t/, $line); |
2605 |
$min = hex $min; |
2606 |
if (length $max) { |
2607 |
$max = hex $max; |
2608 |
} else { |
2609 |
$max = $min; |
2610 |
} |
2611 |
$result = hex $result; |
2612 |
if ($result == $extra) { |
2613 |
push @delfrom, [$min, $max]; |
2614 |
} else { |
2615 |
push @from, [$min, $max]; |
2616 |
push @to, [$result, $result + $max - $min]; |
2617 |
} |
2618 |
} |
2619 |
for my $i (0 .. $#from) { |
2620 |
if ($from[$i][0] == ord '-') { |
2621 |
unshift @from, splice(@from, $i, 1); |
2622 |
unshift @to, splice(@to, $i, 1); |
2623 |
last; |
2624 |
} elsif ($from[$i][1] == ord '-') { |
2625 |
$from[$i][1]--; |
2626 |
$to[$i][1]--; |
2627 |
unshift @from, ord '-'; |
2628 |
unshift @to, ord '-'; |
2629 |
last; |
2630 |
} |
2631 |
} |
2632 |
for my $i (0 .. $#delfrom) { |
2633 |
if ($delfrom[$i][0] == ord '-') { |
2634 |
push @delfrom, splice(@delfrom, $i, 1); |
2635 |
last; |
2636 |
} elsif ($delfrom[$i][1] == ord '-') { |
2637 |
$delfrom[$i][1]--; |
2638 |
push @delfrom, ord '-'; |
2639 |
last; |
2640 |
} |
2641 |
} |
2642 |
if (defined $final and $to[$#to][1] != $final) { |
2643 |
push @to, [$final, $final]; |
2644 |
} |
2645 |
push @from, @delfrom; |
2646 |
if ($flags & OPpTRANS_COMPLEMENT) { |
2647 |
my @newfrom; |
2648 |
my $next = 0; |
2649 |
for my $i (0 .. $#from) { |
2650 |
push @newfrom, [$next, $from[$i][0] - 1]; |
2651 |
$next = $from[$i][1] + 1; |
2652 |
} |
2653 |
@from = (); |
2654 |
for my $range (@newfrom) { |
2655 |
if ($range->[0] <= $range->[1]) { |
2656 |
push @from, $range; |
2657 |
} |
2658 |
} |
2659 |
} |
2660 |
my($from, $to, $diff); |
2661 |
for my $chunk (@from) { |
2662 |
$diff = $chunk->[1] - $chunk->[0]; |
2663 |
if ($diff > 1) { |
2664 |
$from .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]); |
2665 |
} elsif ($diff == 1) { |
2666 |
$from .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]); |
2667 |
} else { |
2668 |
$from .= tr_chr($chunk->[0]); |
2669 |
} |
2670 |
} |
2671 |
for my $chunk (@to) { |
2672 |
$diff = $chunk->[1] - $chunk->[0]; |
2673 |
if ($diff > 1) { |
2674 |
$to .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]); |
2675 |
} elsif ($diff == 1) { |
2676 |
$to .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]); |
2677 |
} else { |
2678 |
$to .= tr_chr($chunk->[0]); |
2679 |
} |
2680 |
} |
2681 |
#$final = sprintf("%04x", $final) if defined $final; |
2682 |
#$none = sprintf("%04x", $none) if defined $none; |
2683 |
#$extra = sprintf("%04x", $extra) if defined $extra; |
2684 |
#print STDERR "final: $final\n none: $none\nextra: $extra\n"; |
2685 |
#print STDERR $swash{'LIST'}->PV; |
2686 |
return (escape_str($from), escape_str($to)); |
2687 |
} |
2688 |
|
2689 |
sub pp_trans { |
2690 |
my $self = shift; |
2691 |
my($op, $cx) = @_; |
2692 |
my($from, $to); |
2693 |
if (class($op) eq "PVOP") { |
2694 |
($from, $to) = tr_decode_byte($op->pv, $op->private); |
2695 |
} else { # class($op) eq "SVOP" |
2696 |
($from, $to) = tr_decode_utf8($op->sv->RV, $op->private); |
2697 |
} |
2698 |
my $flags = ""; |
2699 |
$flags .= "c" if $op->private & OPpTRANS_COMPLEMENT; |
2700 |
$flags .= "d" if $op->private & OPpTRANS_DELETE; |
2701 |
$to = "" if $from eq $to and $flags eq ""; |
2702 |
$flags .= "s" if $op->private & OPpTRANS_SQUASH; |
2703 |
return "tr" . double_delim($from, $to) . $flags; |
2704 |
} |
2705 |
|
2706 |
# Like dq(), but different |
2707 |
sub re_dq { |
2708 |
my $self = shift; |
2709 |
my $op = shift; |
2710 |
my $type = $op->name; |
2711 |
if ($type eq "const") { |
2712 |
return re_uninterp($self->const_sv($op)->PV); |
2713 |
} elsif ($type eq "concat") { |
2714 |
my $first = $self->re_dq($op->first); |
2715 |
my $last = $self->re_dq($op->last); |
2716 |
# Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]" |
2717 |
if ($last =~ /^[{\[\w]/) { |
2718 |
$first =~ s/([%\$@])([A-Za-z_]\w*)$/${1}{$2}/; |
2719 |
} |
2720 |
return $first . $last; |
2721 |
} elsif ($type eq "uc") { |
2722 |
return '\U' . $self->re_dq($op->first->sibling) . '\E'; |
2723 |
} elsif ($type eq "lc") { |
2724 |
return '\L' . $self->re_dq($op->first->sibling) . '\E'; |
2725 |
} elsif ($type eq "ucfirst") { |
2726 |
return '\u' . $self->re_dq($op->first->sibling); |
2727 |
} elsif ($type eq "lcfirst") { |
2728 |
return '\l' . $self->re_dq($op->first->sibling); |
2729 |
} elsif ($type eq "quotemeta") { |
2730 |
return '\Q' . $self->re_dq($op->first->sibling) . '\E'; |
2731 |
} elsif ($type eq "join") { |
2732 |
return $self->deparse($op->last, 26); # was join($", @ary) |
2733 |
} else { |
2734 |
return $self->deparse($op, 26); |
2735 |
} |
2736 |
} |
2737 |
|
2738 |
sub pp_regcomp { |
2739 |
my $self = shift; |
2740 |
my($op, $cx) = @_; |
2741 |
my $kid = $op->first; |
2742 |
$kid = $kid->first if $kid->name eq "regcmaybe"; |
2743 |
$kid = $kid->first if $kid->name eq "regcreset"; |
2744 |
return $self->re_dq($kid); |
2745 |
} |
2746 |
|
2747 |
# osmic acid -- see osmium tetroxide |
2748 |
|
2749 |
my %matchwords; |
2750 |
map($matchwords{join "", sort split //, $_} = $_, 'cig', 'cog', 'cos', 'cogs', |
2751 |
'cox', 'go', 'is', 'ism', 'iso', 'mig', 'mix', 'osmic', 'ox', 'sic', |
2752 |
'sig', 'six', 'smog', 'so', 'soc', 'sog', 'xi'); |
2753 |
|
2754 |
sub matchop { |
2755 |
my $self = shift; |
2756 |
my($op, $cx, $name, $delim) = @_; |
2757 |
my $kid = $op->first; |
2758 |
my ($binop, $var, $re) = ("", "", ""); |
2759 |
if ($op->flags & OPf_STACKED) { |
2760 |
$binop = 1; |
2761 |
$var = $self->deparse($kid, 20); |
2762 |
$kid = $kid->sibling; |
2763 |
} |
2764 |
if (null $kid) { |
2765 |
$re = re_uninterp(escape_str($op->precomp)); |
2766 |
} else { |
2767 |
$re = $self->deparse($kid, 1); |
2768 |
} |
2769 |
my $flags = ""; |
2770 |
$flags .= "c" if $op->pmflags & PMf_CONTINUE; |
2771 |
$flags .= "g" if $op->pmflags & PMf_GLOBAL; |
2772 |
$flags .= "i" if $op->pmflags & PMf_FOLD; |
2773 |
$flags .= "m" if $op->pmflags & PMf_MULTILINE; |
2774 |
$flags .= "o" if $op->pmflags & PMf_KEEP; |
2775 |
$flags .= "s" if $op->pmflags & PMf_SINGLELINE; |
2776 |
$flags .= "x" if $op->pmflags & PMf_EXTENDED; |
2777 |
$flags = $matchwords{$flags} if $matchwords{$flags}; |
2778 |
if ($op->pmflags & PMf_ONCE) { # only one kind of delimiter works here |
2779 |
$re =~ s/\?/\\?/g; |
2780 |
$re = "?$re?"; |
2781 |
} else { |
2782 |
$re = single_delim($name, $delim, $re); |
2783 |
} |
2784 |
$re = $re . $flags; |
2785 |
if ($binop) { |
2786 |
return $self->maybe_parens("$var =~ $re", $cx, 20); |
2787 |
} else { |
2788 |
return $re; |
2789 |
} |
2790 |
} |
2791 |
|
2792 |
sub pp_match { matchop(@_, "m", "/") } |
2793 |
sub pp_pushre { matchop(@_, "m", "/") } |
2794 |
sub pp_qr { matchop(@_, "qr", "") } |
2795 |
|
2796 |
sub pp_split { |
2797 |
my $self = shift; |
2798 |
my($op, $cx) = @_; |
2799 |
my($kid, @exprs, $ary, $expr); |
2800 |
$kid = $op->first; |
2801 |
if ($ {$kid->pmreplroot}) { |
2802 |
$ary = '@' . $self->gv_name($kid->pmreplroot); |
2803 |
} |
2804 |
for (; !null($kid); $kid = $kid->sibling) { |
2805 |
push @exprs, $self->deparse($kid, 6); |
2806 |
} |
2807 |
$expr = "split(" . join(", ", @exprs) . ")"; |
2808 |
if ($ary) { |
2809 |
return $self->maybe_parens("$ary = $expr", $cx, 7); |
2810 |
} else { |
2811 |
return $expr; |
2812 |
} |
2813 |
} |
2814 |
|
2815 |
# oxime -- any of various compounds obtained chiefly by the action of |
2816 |
# hydroxylamine on aldehydes and ketones and characterized by the |
2817 |
# bivalent grouping C=NOH [Webster's Tenth] |
2818 |
|
2819 |
my %substwords; |
2820 |
map($substwords{join "", sort split //, $_} = $_, 'ego', 'egoism', 'em', |
2821 |
'es', 'ex', 'exes', 'gee', 'go', 'goes', 'ie', 'ism', 'iso', 'me', |
2822 |
'meese', 'meso', 'mig', 'mix', 'os', 'ox', 'oxime', 'see', 'seem', |
2823 |
'seg', 'sex', 'sig', 'six', 'smog', 'sog', 'some', 'xi'); |
2824 |
|
2825 |
sub pp_subst { |
2826 |
my $self = shift; |
2827 |
my($op, $cx) = @_; |
2828 |
my $kid = $op->first; |
2829 |
my($binop, $var, $re, $repl) = ("", "", "", ""); |
2830 |
if ($op->flags & OPf_STACKED) { |
2831 |
$binop = 1; |
2832 |
$var = $self->deparse($kid, 20); |
2833 |
$kid = $kid->sibling; |
2834 |
} |
2835 |
my $flags = ""; |
2836 |
if (null($op->pmreplroot)) { |
2837 |
$repl = $self->dq($kid); |
2838 |
$kid = $kid->sibling; |
2839 |
} else { |
2840 |
$repl = $op->pmreplroot->first; # skip substcont |
2841 |
while ($repl->name eq "entereval") { |
2842 |
$repl = $repl->first; |
2843 |
$flags .= "e"; |
2844 |
} |
2845 |
if ($op->pmflags & PMf_EVAL) { |
2846 |
$repl = $self->deparse($repl, 0); |
2847 |
} else { |
2848 |
$repl = $self->dq($repl); |
2849 |
} |
2850 |
} |
2851 |
if (null $kid) { |
2852 |
$re = re_uninterp(escape_str($op->precomp)); |
2853 |
} else { |
2854 |
$re = $self->deparse($kid, 1); |
2855 |
} |
2856 |
$flags .= "e" if $op->pmflags & PMf_EVAL; |
2857 |
$flags .= "g" if $op->pmflags & PMf_GLOBAL; |
2858 |
$flags .= "i" if $op->pmflags & PMf_FOLD; |
2859 |
$flags .= "m" if $op->pmflags & PMf_MULTILINE; |
2860 |
$flags .= "o" if $op->pmflags & PMf_KEEP; |
2861 |
$flags .= "s" if $op->pmflags & PMf_SINGLELINE; |
2862 |
$flags .= "x" if $op->pmflags & PMf_EXTENDED; |
2863 |
$flags = $substwords{$flags} if $substwords{$flags}; |
2864 |
if ($binop) { |
2865 |
return $self->maybe_parens("$var =~ s" |
2866 |
. double_delim($re, $repl) . $flags, |
2867 |
$cx, 20); |
2868 |
} else { |
2869 |
return "s". double_delim($re, $repl) . $flags; |
2870 |
} |
2871 |
} |
2872 |
|
2873 |
1; |
2874 |
__END__ |
2875 |
|
2876 |
=head1 NAME |
2877 |
|
2878 |
B::Deparse - Perl compiler backend to produce perl code |
2879 |
|
2880 |
=head1 SYNOPSIS |
2881 |
|
2882 |
B<perl> B<-MO=Deparse>[B<,-u>I<PACKAGE>][B<,-p>][B<,-q>][B<,-l>] |
2883 |
[B<,-s>I<LETTERS>][B<,-x>I<LEVEL>] I<prog.pl> |
2884 |
|
2885 |
=head1 DESCRIPTION |
2886 |
|
2887 |
B::Deparse is a backend module for the Perl compiler that generates |
2888 |
perl source code, based on the internal compiled structure that perl |
2889 |
itself creates after parsing a program. The output of B::Deparse won't |
2890 |
be exactly the same as the original source, since perl doesn't keep |
2891 |
track of comments or whitespace, and there isn't a one-to-one |
2892 |
correspondence between perl's syntactical constructions and their |
2893 |
compiled form, but it will often be close. When you use the B<-p> |
2894 |
option, the output also includes parentheses even when they are not |
2895 |
required by precedence, which can make it easy to see if perl is |
2896 |
parsing your expressions the way you intended. |
2897 |
|
2898 |
Please note that this module is mainly new and untested code and is |
2899 |
still under development, so it may change in the future. |
2900 |
|
2901 |
=head1 OPTIONS |
2902 |
|
2903 |
As with all compiler backend options, these must follow directly after |
2904 |
the '-MO=Deparse', separated by a comma but not any white space. |
2905 |
|
2906 |
=over 4 |
2907 |
|
2908 |
=item B<-l> |
2909 |
|
2910 |
Add '#line' declarations to the output based on the line and file |
2911 |
locations of the original code. |
2912 |
|
2913 |
=item B<-p> |
2914 |
|
2915 |
Print extra parentheses. Without this option, B::Deparse includes |
2916 |
parentheses in its output only when they are needed, based on the |
2917 |
structure of your program. With B<-p>, it uses parentheses (almost) |
2918 |
whenever they would be legal. This can be useful if you are used to |
2919 |
LISP, or if you want to see how perl parses your input. If you say |
2920 |
|
2921 |
if ($var & 0x7f == 65) {print "Gimme an A!"} |
2922 |
print ($which ? $a : $b), "\n"; |
2923 |
$name = $ENV{USER} or "Bob"; |
2924 |
|
2925 |
C<B::Deparse,-p> will print |
2926 |
|
2927 |
if (($var & 0)) { |
2928 |
print('Gimme an A!') |
2929 |
}; |
2930 |
(print(($which ? $a : $b)), '???'); |
2931 |
(($name = $ENV{'USER'}) or '???') |
2932 |
|
2933 |
which probably isn't what you intended (the C<'???'> is a sign that |
2934 |
perl optimized away a constant value). |
2935 |
|
2936 |
=item B<-q> |
2937 |
|
2938 |
Expand double-quoted strings into the corresponding combinations of |
2939 |
concatenation, uc, ucfirst, lc, lcfirst, quotemeta, and join. For |
2940 |
instance, print |
2941 |
|
2942 |
print "Hello, $world, @ladies, \u$gentlemen\E, \u\L$me!"; |
2943 |
|
2944 |
as |
2945 |
|
2946 |
print 'Hello, ' . $world . ', ' . join($", @ladies) . ', ' |
2947 |
. ucfirst($gentlemen) . ', ' . ucfirst(lc $me . '!'); |
2948 |
|
2949 |
Note that the expanded form represents the way perl handles such |
2950 |
constructions internally -- this option actually turns off the reverse |
2951 |
translation that B::Deparse usually does. On the other hand, note that |
2952 |
C<$x = "$y"> is not the same as C<$x = $y>: the former makes the value |
2953 |
of $y into a string before doing the assignment. |
2954 |
|
2955 |
=item B<-u>I<PACKAGE> |
2956 |
|
2957 |
Normally, B::Deparse deparses the main code of a program, all the subs |
2958 |
called by the main program (and all the subs called by them, |
2959 |
recursively), and any other subs in the main:: package. To include |
2960 |
subs in other packages that aren't called directly, such as AUTOLOAD, |
2961 |
DESTROY, other subs called automatically by perl, and methods (which |
2962 |
aren't resolved to subs until runtime), use the B<-u> option. The |
2963 |
argument to B<-u> is the name of a package, and should follow directly |
2964 |
after the 'u'. Multiple B<-u> options may be given, separated by |
2965 |
commas. Note that unlike some other backends, B::Deparse doesn't |
2966 |
(yet) try to guess automatically when B<-u> is needed -- you must |
2967 |
invoke it yourself. |
2968 |
|
2969 |
=item B<-s>I<LETTERS> |
2970 |
|
2971 |
Tweak the style of B::Deparse's output. The letters should follow |
2972 |
directly after the 's', with no space or punctuation. The following |
2973 |
options are available: |
2974 |
|
2975 |
=over 4 |
2976 |
|
2977 |
=item B<C> |
2978 |
|
2979 |
Cuddle C<elsif>, C<else>, and C<continue> blocks. For example, print |
2980 |
|
2981 |
if (...) { |
2982 |
... |
2983 |
} else { |
2984 |
... |
2985 |
} |
2986 |
|
2987 |
instead of |
2988 |
|
2989 |
if (...) { |
2990 |
... |
2991 |
} |
2992 |
else { |
2993 |
... |
2994 |
} |
2995 |
|
2996 |
The default is not to cuddle. |
2997 |
|
2998 |
=item B<i>I<NUMBER> |
2999 |
|
3000 |
Indent lines by multiples of I<NUMBER> columns. The default is 4 columns. |
3001 |
|
3002 |
=item B<T> |
3003 |
|
3004 |
Use tabs for each 8 columns of indent. The default is to use only spaces. |
3005 |
For instance, if the style options are B<-si4T>, a line that's indented |
3006 |
3 times will be preceded by one tab and four spaces; if the options were |
3007 |
B<-si8T>, the same line would be preceded by three tabs. |
3008 |
|
3009 |
=item B<v>I<STRING>B<.> |
3010 |
|
3011 |
Print I<STRING> for the value of a constant that can't be determined |
3012 |
because it was optimized away (mnemonic: this happens when a constant |
3013 |
is used in B<v>oid context). The end of the string is marked by a period. |
3014 |
The string should be a valid perl expression, generally a constant. |
3015 |
Note that unless it's a number, it probably needs to be quoted, and on |
3016 |
a command line quotes need to be protected from the shell. Some |
3017 |
conventional values include 0, 1, 42, '', 'foo', and |
3018 |
'Useless use of constant omitted' (which may need to be |
3019 |
B<-sv"'Useless use of constant omitted'."> |
3020 |
or something similar depending on your shell). The default is '???'. |
3021 |
If you're using B::Deparse on a module or other file that's require'd, |
3022 |
you shouldn't use a value that evaluates to false, since the customary |
3023 |
true constant at the end of a module will be in void context when the |
3024 |
file is compiled as a main program. |
3025 |
|
3026 |
=back |
3027 |
|
3028 |
=item B<-x>I<LEVEL> |
3029 |
|
3030 |
Expand conventional syntax constructions into equivalent ones that expose |
3031 |
their internal operation. I<LEVEL> should be a digit, with higher values |
3032 |
meaning more expansion. As with B<-q>, this actually involves turning off |
3033 |
special cases in B::Deparse's normal operations. |
3034 |
|
3035 |
If I<LEVEL> is at least 3, for loops will be translated into equivalent |
3036 |
while loops with continue blocks; for instance |
3037 |
|
3038 |
for ($i = 0; $i < 10; ++$i) { |
3039 |
print $i; |
3040 |
} |
3041 |
|
3042 |
turns into |
3043 |
|
3044 |
$i = 0; |
3045 |
while ($i < 10) { |
3046 |
print $i; |
3047 |
} continue { |
3048 |
++$i |
3049 |
} |
3050 |
|
3051 |
Note that in a few cases this translation can't be perfectly carried back |
3052 |
into the source code -- if the loop's initializer declares a my variable, |
3053 |
for instance, it won't have the correct scope outside of the loop. |
3054 |
|
3055 |
If I<LEVEL> is at least 7, if statements will be translated into equivalent |
3056 |
expressions using C<&&>, C<?:> and C<do {}>; for instance |
3057 |
|
3058 |
print 'hi' if $nice; |
3059 |
if ($nice) { |
3060 |
print 'hi'; |
3061 |
} |
3062 |
if ($nice) { |
3063 |
print 'hi'; |
3064 |
} else { |
3065 |
print 'bye'; |
3066 |
} |
3067 |
|
3068 |
turns into |
3069 |
|
3070 |
$nice and print 'hi'; |
3071 |
$nice and do { print 'hi' }; |
3072 |
$nice ? do { print 'hi' } : do { print 'bye' }; |
3073 |
|
3074 |
Long sequences of elsifs will turn into nested ternary operators, which |
3075 |
B::Deparse doesn't know how to indent nicely. |
3076 |
|
3077 |
=back |
3078 |
|
3079 |
=head1 USING B::Deparse AS A MODULE |
3080 |
|
3081 |
=head2 Synopsis |
3082 |
|
3083 |
use B::Deparse; |
3084 |
$deparse = B::Deparse->new("-p", "-sC"); |
3085 |
$body = $deparse->coderef2text(\&func); |
3086 |
eval "sub func $body"; # the inverse operation |
3087 |
|
3088 |
=head2 Description |
3089 |
|
3090 |
B::Deparse can also be used on a sub-by-sub basis from other perl |
3091 |
programs. |
3092 |
|
3093 |
=head2 new |
3094 |
|
3095 |
$deparse = B::Deparse->new(OPTIONS) |
3096 |
|
3097 |
Create an object to store the state of a deparsing operation and any |
3098 |
options. The options are the same as those that can be given on the |
3099 |
command line (see L</OPTIONS>); options that are separated by commas |
3100 |
after B<-MO=Deparse> should be given as separate strings. Some |
3101 |
options, like B<-u>, don't make sense for a single subroutine, so |
3102 |
don't pass them. |
3103 |
|
3104 |
=head2 coderef2text |
3105 |
|
3106 |
$body = $deparse->coderef2text(\&func) |
3107 |
$body = $deparse->coderef2text(sub ($$) { ... }) |
3108 |
|
3109 |
Return source code for the body of a subroutine (a block, optionally |
3110 |
preceded by a prototype in parens), given a reference to the |
3111 |
sub. Because a subroutine can have no names, or more than one name, |
3112 |
this method doesn't return a complete subroutine definition -- if you |
3113 |
want to eval the result, you should prepend "sub subname ", or "sub " |
3114 |
for an anonymous function constructor. Unless the sub was defined in |
3115 |
the main:: package, the code will include a package declaration. |
3116 |
|
3117 |
=head1 BUGS |
3118 |
|
3119 |
See the 'to do' list at the beginning of the module file. |
3120 |
|
3121 |
=head1 AUTHOR |
3122 |
|
3123 |
Stephen McCamant <smcc@CSUA.Berkeley.EDU>, based on an earlier |
3124 |
version by Malcolm Beattie <mbeattie@sable.ox.ac.uk>, with |
3125 |
contributions from Gisle Aas, James Duncan, Albert Dvornik, Hugo van |
3126 |
der Sanden, Gurusamy Sarathy, and Nick Ing-Simmons. |
3127 |
|
3128 |
=cut |