Extra tweakage from Rafael for #19392.
[p5sagit/p5-mst-13.2.git] / ext / B / B / Concise.pm
CommitLineData
c99ca59a 1package B::Concise;
c27ea44e 2# Copyright (C) 2000-2003 Stephen McCamant. All rights reserved.
c99ca59a 3# This program is free software; you can redistribute and/or modify it
4# under the same terms as Perl itself.
5
c99ca59a 6use strict;
78ad9108 7use warnings;
8
9use Exporter ();
10
31b49ad4 11our $VERSION = "0.55";
78ad9108 12our @ISA = qw(Exporter);
31b49ad4 13our @EXPORT_OK = qw(set_style set_style_standard add_callback
14 concise_cv concise_main);
78ad9108 15
c99ca59a 16use B qw(class ppname main_start main_root main_cv cstring svref_2object
31b49ad4 17 SVf_IOK SVf_NOK SVf_POK SVf_IVisUV OPf_KIDS);
c99ca59a 18
19my %style =
20 ("terse" =>
c3caa09d 21 ["(?(#label =>\n)?)(*( )*)#class (#addr) #name (?([#targ])?) "
22 . "#svclass~(?((#svaddr))?)~#svval~(?(label \"#coplabel\")?)\n",
c99ca59a 23 "(*( )*)goto #class (#addr)\n",
24 "#class pp_#name"],
25 "concise" =>
26 ["#hyphseq2 (*( (x( ;)x))*)<#classsym> "
27 . "#exname#arg(?([#targarglife])?)~#flags(?(/#private)?)(x(;~->#next)x)\n",
28 " (*( )*) goto #seq\n",
29 "(?(<#seq>)?)#exname#arg(?([#targarglife])?)"],
30 "linenoise" =>
31 ["(x(;(*( )*))x)#noise#arg(?([#targarg])?)(x( ;\n)x)",
32 "gt_#seq ",
33 "(?(#seq)?)#noise#arg(?([#targarg])?)"],
34 "debug" =>
35 ["#class (#addr)\n\top_next\t\t#nextaddr\n\top_sibling\t#sibaddr\n\t"
36 . "op_ppaddr\tPL_ppaddr[OP_#NAME]\n\top_type\t\t#typenum\n\top_seq\t\t"
37 . "#seqnum\n\top_flags\t#flagval\n\top_private\t#privval\n"
38 . "(?(\top_first\t#firstaddr\n)?)(?(\top_last\t\t#lastaddr\n)?)"
39 . "(?(\top_sv\t\t#svaddr\n)?)",
40 " GOTO #addr\n",
41 "#addr"],
42 "env" => [$ENV{B_CONCISE_FORMAT}, $ENV{B_CONCISE_GOTO_FORMAT},
43 $ENV{B_CONCISE_TREE_FORMAT}],
44 );
45
46my($format, $gotofmt, $treefmt);
47my $curcv;
c27ea44e 48my $cop_seq_base;
78ad9108 49my @callbacks;
50
51sub set_style {
52 ($format, $gotofmt, $treefmt) = @_;
53}
54
31b49ad4 55sub set_style_standard {
56 my($name) = @_;
57 set_style(@{$style{$name}});
58}
59
78ad9108 60sub add_callback {
61 push @callbacks, @_;
62}
c99ca59a 63
64sub concise_cv {
65 my ($order, $cvref) = @_;
66 my $cv = svref_2object($cvref);
67 $curcv = $cv;
c27ea44e 68 sequence($cv->START);
c99ca59a 69 if ($order eq "exec") {
70 walk_exec($cv->START);
71 } elsif ($order eq "basic") {
72 walk_topdown($cv->ROOT, sub { $_[0]->concise($_[1]) }, 0);
73 } else {
74 print tree($cv->ROOT, 0)
75 }
76}
77
31b49ad4 78sub concise_main {
79 my($order) = @_;
80 sequence(main_start);
81 $curcv = main_cv;
82 if ($order eq "exec") {
83 return if class(main_start) eq "NULL";
84 walk_exec(main_start);
85 } elsif ($order eq "tree") {
86 return if class(main_root) eq "NULL";
87 print tree(main_root, 0);
88 } elsif ($order eq "basic") {
89 return if class(main_root) eq "NULL";
90 walk_topdown(main_root,
91 sub { $_[0]->concise($_[1]) }, 0);
92 }
93}
94
c99ca59a 95my $start_sym = "\e(0"; # "\cN" sometimes also works
96my $end_sym = "\e(B"; # "\cO" respectively
97
98my @tree_decorations =
99 ([" ", "--", "+-", "|-", "| ", "`-", "-", 1],
100 [" ", "-", "+", "+", "|", "`", "", 0],
101 [" ", map("$start_sym$_$end_sym", "qq", "wq", "tq", "x ", "mq", "q"), 1],
102 [" ", map("$start_sym$_$end_sym", "q", "w", "t", "x", "m"), "", 0],
103 );
104my $tree_style = 0;
105
106my $base = 36;
107my $big_endian = 1;
108
109my $order = "basic";
110
31b49ad4 111set_style_standard("concise");
78ad9108 112
c99ca59a 113sub compile {
114 my @options = grep(/^-/, @_);
115 my @args = grep(!/^-/, @_);
116 my $do_main = 0;
c99ca59a 117 for my $o (@options) {
118 if ($o eq "-basic") {
119 $order = "basic";
120 } elsif ($o eq "-exec") {
121 $order = "exec";
122 } elsif ($o eq "-tree") {
123 $order = "tree";
124 } elsif ($o eq "-compact") {
125 $tree_style |= 1;
126 } elsif ($o eq "-loose") {
127 $tree_style &= ~1;
128 } elsif ($o eq "-vt") {
129 $tree_style |= 2;
130 } elsif ($o eq "-ascii") {
131 $tree_style &= ~2;
132 } elsif ($o eq "-main") {
133 $do_main = 1;
134 } elsif ($o =~ /^-base(\d+)$/) {
135 $base = $1;
136 } elsif ($o eq "-bigendian") {
137 $big_endian = 1;
138 } elsif ($o eq "-littleendian") {
139 $big_endian = 0;
140 } elsif (exists $style{substr($o, 1)}) {
78ad9108 141 set_style(@{$style{substr($o, 1)}});
c99ca59a 142 } else {
143 warn "Option $o unrecognized";
144 }
145 }
c27ea44e 146 return sub {
147 if (@args) {
c99ca59a 148 for my $objname (@args) {
149 $objname = "main::" . $objname unless $objname =~ /::/;
c27ea44e 150 print "$objname:\n";
c99ca59a 151 eval "concise_cv(\$order, \\&$objname)";
152 die "concise_cv($order, \\&$objname) failed: $@" if $@;
153 }
154 }
c27ea44e 155 if (!@args or $do_main) {
156 print "main program:\n" if $do_main;
31b49ad4 157 concise_main($order);
c99ca59a 158 }
159 }
160}
161
162my %labels;
163my $lastnext;
164
165my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
166 'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
051f02e9 167 'PVOP' => '"', 'LOOP' => "{", 'COP' => ";", 'PADOP' => "#");
c99ca59a 168
35fc55f1 169no warnings 'qw'; # "Possible attempt to put comments..."
170my @linenoise =
171 qw'# () sc ( @? 1 $* gv *{ m$ m@ m% m? p/ *$ $ $# & a& pt \\ s\\ rf bl
c99ca59a 172 ` *? <> ?? ?/ r/ c/ // qr s/ /c y/ = @= C sC Cp sp df un BM po +1 +I
173 -1 -I 1+ I+ 1- I- ** * i* / i/ %$ i% x + i+ - i- . " << >> < i<
174 > i> <= i, >= i. == i= != i! <? i? s< s> s, s. s= s! s? b& b^ b| -0 -i
175 ! ~ a2 si cs rd sr e^ lg sq in %x %o ab le ss ve ix ri sf FL od ch cy
176 uf lf uc lc qm @ [f [ @[ eh vl ky dl ex % ${ @{ uk pk st jn ) )[ a@
177 a% sl +] -] [- [+ so rv GS GW MS MW .. f. .f && || ^^ ?: &= |= -> s{ s}
178 v} ca wa di rs ;; ; ;d }{ { } {} f{ it {l l} rt }l }n }r dm }g }e ^o
179 ^c ^| ^# um bm t~ u~ ~d DB db ^s se ^g ^r {w }w pf pr ^O ^K ^R ^W ^d ^v
180 ^e ^t ^k t. fc ic fl .s .p .b .c .l .a .h g1 s1 g2 s2 ?. l? -R -W -X -r
181 -w -x -e -o -O -z -s -M -A -C -S -c -b -f -d -p -l -u -g -k -t -T -B cd
182 co cr u. cm ut r. l@ s@ r@ mD uD oD rD tD sD wD cD f$ w$ p$ sh e$ k$ g3
183 g4 s4 g5 s5 T@ C@ L@ G@ A@ S@ Hg Hc Hr Hw Mg Mc Ms Mr Sg Sc So rq do {e
184 e} {t t} g6 G6 6e g7 G7 7e g8 G8 8e g9 G9 9e 6s 7s 8s 9s 6E 7E 8E 9E Pn
c27ea44e 185 Pu GP SP EP Gn Gg GG SG EG g0 c$ lk t$ ;s n> // /= CO';
c99ca59a 186
187my $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
188
189sub op_flags {
190 my($x) = @_;
191 my(@v);
192 push @v, "v" if ($x & 3) == 1;
193 push @v, "s" if ($x & 3) == 2;
194 push @v, "l" if ($x & 3) == 3;
195 push @v, "K" if $x & 4;
196 push @v, "P" if $x & 8;
197 push @v, "R" if $x & 16;
198 push @v, "M" if $x & 32;
199 push @v, "S" if $x & 64;
200 push @v, "*" if $x & 128;
201 return join("", @v);
202}
203
204sub base_n {
205 my $x = shift;
206 return "-" . base_n(-$x) if $x < 0;
207 my $str = "";
208 do { $str .= substr($chars, $x % $base, 1) } while $x = int($x / $base);
209 $str = reverse $str if $big_endian;
210 return $str;
211}
212
c27ea44e 213my %sequence_num;
214my $seq_max = 1;
215
216sub seq {
217 my($op) = @_;
218 return "-" if not exists $sequence_num{$$op};
219 return base_n($sequence_num{$$op});
220}
c99ca59a 221
222sub walk_topdown {
223 my($op, $sub, $level) = @_;
224 $sub->($op, $level);
225 if ($op->flags & OPf_KIDS) {
226 for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
227 walk_topdown($kid, $sub, $level + 1);
228 }
229 }
31b49ad4 230 if (class($op) eq "PMOP" and $op->pmreplroot and $ {$op->pmreplroot}
b2a3cfdd 231 and $op->pmreplroot->isa("B::OP")) {
c99ca59a 232 walk_topdown($op->pmreplroot, $sub, $level + 1);
233 }
234}
235
236sub walklines {
237 my($ar, $level) = @_;
238 for my $l (@$ar) {
239 if (ref($l) eq "ARRAY") {
240 walklines($l, $level + 1);
241 } else {
242 $l->concise($level);
243 }
244 }
245}
246
247sub walk_exec {
248 my($top, $level) = @_;
249 my %opsseen;
250 my @lines;
251 my @todo = ([$top, \@lines]);
252 while (@todo and my($op, $targ) = @{shift @todo}) {
253 for (; $$op; $op = $op->next) {
254 last if $opsseen{$$op}++;
255 push @$targ, $op;
256 my $name = $op->name;
62e36f8a 257 if (class($op) eq "LOGOP") {
c99ca59a 258 my $ar = [];
259 push @$targ, $ar;
260 push @todo, [$op->other, $ar];
261 } elsif ($name eq "subst" and $ {$op->pmreplstart}) {
262 my $ar = [];
263 push @$targ, $ar;
264 push @todo, [$op->pmreplstart, $ar];
265 } elsif ($name =~ /^enter(loop|iter)$/) {
266 $labels{$op->nextop->seq} = "NEXT";
267 $labels{$op->lastop->seq} = "LAST";
268 $labels{$op->redoop->seq} = "REDO";
269 }
270 }
271 }
272 walklines(\@lines, 0);
273}
274
c27ea44e 275# The structure of this routine is purposely modeled after op.c's peep()
276sub sequence {
277 my($op) = @_;
278 my $oldop = 0;
279 return if class($op) eq "NULL" or exists $sequence_num{$$op};
280 for (; $$op; $op = $op->next) {
281 last if exists $sequence_num{$$op};
282 my $name = $op->name;
283 if ($name =~ /^(null|scalar|lineseq|scope)$/) {
284 next if $oldop and $ {$op->next};
285 } else {
286 $sequence_num{$$op} = $seq_max++;
287 if (class($op) eq "LOGOP") {
288 my $other = $op->other;
289 $other = $other->next while $other->name eq "null";
290 sequence($other);
291 } elsif (class($op) eq "LOOP") {
292 my $redoop = $op->redoop;
293 $redoop = $redoop->next while $redoop->name eq "null";
294 sequence($redoop);
295 my $nextop = $op->nextop;
296 $nextop = $nextop->next while $nextop->name eq "null";
297 sequence($nextop);
298 my $lastop = $op->lastop;
299 $lastop = $lastop->next while $lastop->name eq "null";
300 sequence($lastop);
301 } elsif ($name eq "subst" and $ {$op->pmreplstart}) {
302 my $replstart = $op->pmreplstart;
303 $replstart = $replstart->next while $replstart->name eq "null";
304 sequence($replstart);
305 }
306 }
307 $oldop = $op;
308 }
309}
310
c99ca59a 311sub fmt_line {
312 my($hr, $fmt, $level) = @_;
313 my $text = $fmt;
314 $text =~ s/\(\?\(([^\#]*?)\#(\w+)([^\#]*?)\)\?\)/
315 $hr->{$2} ? $1.$hr->{$2}.$3 : ""/eg;
316 $text =~ s/\(x\((.*?);(.*?)\)x\)/$order eq "exec" ? $1 : $2/egs;
317 $text =~ s/\(\*\(([^;]*?)\)\*\)/$1 x $level/egs;
318 $text =~ s/\(\*\((.*?);(.*?)\)\*\)/$1 x ($level - 1) . $2 x ($level>0)/egs;
319 $text =~ s/#([a-zA-Z]+)(\d+)/sprintf("%-$2s", $hr->{$1})/eg;
320 $text =~ s/#([a-zA-Z]+)/$hr->{$1}/eg;
321 $text =~ s/[ \t]*~+[ \t]*/ /g;
322 return $text;
323}
324
325my %priv;
326$priv{$_}{128} = "LVINTRO"
327 for ("pos", "substr", "vec", "threadsv", "gvsv", "rv2sv", "rv2hv", "rv2gv",
328 "rv2av", "rv2arylen", "aelem", "helem", "aslice", "hslice", "padsv",
329 "padav", "padhv");
330$priv{$_}{64} = "REFC" for ("leave", "leavesub", "leavesublv", "leavewrite");
331$priv{"aassign"}{64} = "COMMON";
c99ca59a 332$priv{"sassign"}{64} = "BKWARD";
333$priv{$_}{64} = "RTIME" for ("match", "subst", "substcont");
334@{$priv{"trans"}}{1,2,4,8,16,64} = ("<UTF", ">UTF", "IDENT", "SQUASH", "DEL",
335 "COMPL", "GROWS");
336$priv{"repeat"}{64} = "DOLIST";
337$priv{"leaveloop"}{64} = "CONT";
338@{$priv{$_}}{32,64,96} = ("DREFAV", "DREFHV", "DREFSV")
339 for ("entersub", map("rv2${_}v", "a", "s", "h", "g"), "aelem", "helem");
340$priv{"entersub"}{16} = "DBG";
341$priv{"entersub"}{32} = "TARG";
342@{$priv{$_}}{4,8,128} = ("INARGS","AMPER","NO()") for ("entersub", "rv2cv");
343$priv{"gv"}{32} = "EARLYCV";
344$priv{"aelem"}{16} = $priv{"helem"}{16} = "LVDEFER";
345$priv{$_}{16} = "OURINTR" for ("gvsv", "rv2sv", "rv2av", "rv2hv", "r2gv");
346$priv{$_}{16} = "TARGMY"
347 for (map(($_,"s$_"),"chop", "chomp"),
348 map(($_,"i_$_"), "postinc", "postdec", "multiply", "divide", "modulo",
349 "add", "subtract", "negate"), "pow", "concat", "stringify",
350 "left_shift", "right_shift", "bit_and", "bit_xor", "bit_or",
351 "complement", "atan2", "sin", "cos", "rand", "exp", "log", "sqrt",
352 "int", "hex", "oct", "abs", "length", "index", "rindex", "sprintf",
353 "ord", "chr", "crypt", "quotemeta", "join", "push", "unshift", "flock",
354 "chdir", "chown", "chroot", "unlink", "chmod", "utime", "rename",
355 "link", "symlink", "mkdir", "rmdir", "wait", "waitpid", "system",
356 "exec", "kill", "getppid", "getpgrp", "setpgrp", "getpriority",
357 "setpriority", "time", "sleep");
7a9b44b9 358@{$priv{"const"}}{8,16,32,64,128} = ("STRICT","ENTERED", '$[', "BARE", "WARN");
c99ca59a 359$priv{"flip"}{64} = $priv{"flop"}{64} = "LINENUM";
360$priv{"list"}{64} = "GUESSED";
361$priv{"delete"}{64} = "SLICE";
362$priv{"exists"}{64} = "SUB";
363$priv{$_}{64} = "LOCALE"
364 for ("sort", "prtf", "sprintf", "slt", "sle", "seq", "sne", "sgt", "sge",
365 "scmp", "lc", "uc", "lcfirst", "ucfirst");
366@{$priv{"sort"}}{1,2,4} = ("NUM", "INT", "REV");
367$priv{"threadsv"}{64} = "SVREFd";
c27ea44e 368@{$priv{$_}}{16,32,64,128} = ("INBIN","INCR","OUTBIN","OUTCR")
369 for ("open", "backtick");
c99ca59a 370$priv{"exit"}{128} = "VMS";
feaeca78 371$priv{$_}{2} = "FTACCESS"
372 for ("ftrread", "ftrwrite", "ftrexec", "fteread", "ftewrite", "fteexec");
c99ca59a 373
374sub private_flags {
375 my($name, $x) = @_;
376 my @s;
377 for my $flag (128, 96, 64, 32, 16, 8, 4, 2, 1) {
378 if ($priv{$name}{$flag} and $x & $flag and $x >= $flag) {
379 $x -= $flag;
380 push @s, $priv{$name}{$flag};
381 }
382 }
383 push @s, $x if $x;
384 return join(",", @s);
385}
386
c27ea44e 387sub concise_sv {
388 my($sv, $hr) = @_;
389 $hr->{svclass} = class($sv);
31b49ad4 390 $hr->{svclass} = "UV"
391 if $hr->{svclass} eq "IV" and $sv->FLAGS & SVf_IVisUV;
c27ea44e 392 $hr->{svaddr} = sprintf("%#x", $$sv);
393 if ($hr->{svclass} eq "GV") {
394 my $gv = $sv;
395 my $stash = $gv->STASH->NAME;
396 if ($stash eq "main") {
397 $stash = "";
398 } else {
399 $stash = $stash . "::";
400 }
401 $hr->{svval} = "*$stash" . $gv->SAFENAME;
402 return "*$stash" . $gv->SAFENAME;
403 } else {
404 while (class($sv) eq "RV") {
405 $hr->{svval} .= "\\";
406 $sv = $sv->RV;
407 }
408 if (class($sv) eq "SPECIAL") {
40b5b14f 409 $hr->{svval} .= ["Null", "sv_undef", "sv_yes", "sv_no"]->[$$sv];
c27ea44e 410 } elsif ($sv->FLAGS & SVf_NOK) {
40b5b14f 411 $hr->{svval} .= $sv->NV;
c27ea44e 412 } elsif ($sv->FLAGS & SVf_IOK) {
31b49ad4 413 $hr->{svval} .= $sv->int_value;
c27ea44e 414 } elsif ($sv->FLAGS & SVf_POK) {
40b5b14f 415 $hr->{svval} .= cstring($sv->PV);
31b49ad4 416 } elsif (class($sv) eq "HV") {
417 $hr->{svval} .= 'HASH';
c27ea44e 418 }
419 return $hr->{svclass} . " " . $hr->{svval};
420 }
421}
422
c99ca59a 423sub concise_op {
424 my ($op, $level, $format) = @_;
425 my %h;
426 $h{exname} = $h{name} = $op->name;
427 $h{NAME} = uc $h{name};
428 $h{class} = class($op);
429 $h{extarg} = $h{targ} = $op->targ;
430 $h{extarg} = "" unless $h{extarg};
431 if ($h{name} eq "null" and $h{targ}) {
432 $h{exname} = "ex-" . substr(ppname($h{targ}), 3);
433 $h{extarg} = "";
434 } elsif ($h{targ}) {
435 my $padname = (($curcv->PADLIST->ARRAY)[0]->ARRAY)[$h{targ}];
436 if (defined $padname and class($padname) ne "SPECIAL") {
0b40bd6d 437 $h{targarg} = $padname->PVX;
c99ca59a 438 my $intro = $padname->NVX - $cop_seq_base;
439 my $finish = int($padname->IVX) - $cop_seq_base;
440 $finish = "end" if $finish == 999999999 - $cop_seq_base;
441 $h{targarglife} = "$h{targarg}:$intro,$finish";
442 } else {
443 $h{targarglife} = $h{targarg} = "t" . $h{targ};
444 }
445 }
446 $h{arg} = "";
447 $h{svclass} = $h{svaddr} = $h{svval} = "";
448 if ($h{class} eq "PMOP") {
449 my $precomp = $op->precomp;
7a9b44b9 450 if (defined $precomp) {
c27ea44e 451 $precomp = cstring($precomp); # Escape literal control sequences
452 $precomp = "/$precomp/";
453 } else {
454 $precomp = "";
7a9b44b9 455 }
b2a3cfdd 456 my $pmreplroot = $op->pmreplroot;
34a48b4b 457 my $pmreplstart;
31b49ad4 458 if ($pmreplroot && $$pmreplroot && $pmreplroot->isa("B::GV")) {
b2a3cfdd 459 # with C<@stash_array = split(/pat/, str);>,
460 # *stash_array is stored in pmreplroot.
461 $h{arg} = "($precomp => \@" . $pmreplroot->NAME . ")";
462 } elsif ($ {$op->pmreplstart}) {
c99ca59a 463 undef $lastnext;
464 $pmreplstart = "replstart->" . seq($op->pmreplstart);
465 $h{arg} = "(" . join(" ", $precomp, $pmreplstart) . ")";
466 } else {
467 $h{arg} = "($precomp)";
468 }
469 } elsif ($h{class} eq "PVOP" and $h{name} ne "trans") {
470 $h{arg} = '("' . $op->pv . '")';
471 $h{svval} = '"' . $op->pv . '"';
472 } elsif ($h{class} eq "COP") {
473 my $label = $op->label;
c3caa09d 474 $h{coplabel} = $label;
c99ca59a 475 $label = $label ? "$label: " : "";
476 my $loc = $op->file;
477 $loc =~ s[.*/][];
478 $loc .= ":" . $op->line;
479 my($stash, $cseq) = ($op->stash->NAME, $op->cop_seq - $cop_seq_base);
480 my $arybase = $op->arybase;
481 $arybase = $arybase ? ' $[=' . $arybase : "";
482 $h{arg} = "($label$stash $cseq $loc$arybase)";
483 } elsif ($h{class} eq "LOOP") {
484 $h{arg} = "(next->" . seq($op->nextop) . " last->" . seq($op->lastop)
485 . " redo->" . seq($op->redoop) . ")";
486 } elsif ($h{class} eq "LOGOP") {
487 undef $lastnext;
488 $h{arg} = "(other->" . seq($op->other) . ")";
489 } elsif ($h{class} eq "SVOP") {
c27ea44e 490 if (! ${$op->sv}) {
491 my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
492 $h{arg} = "[" . concise_sv($sv, \%h) . "]";
493 $h{targarglife} = $h{targarg} = "";
c99ca59a 494 } else {
c27ea44e 495 $h{arg} = "(" . concise_sv($op->sv, \%h) . ")";
c99ca59a 496 }
31b49ad4 497 } elsif ($h{class} eq "PADOP") {
498 my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->padix];
499 $h{arg} = "[" . concise_sv($sv, \%h) . "]";
c99ca59a 500 }
501 $h{seq} = $h{hyphseq} = seq($op);
502 $h{seq} = "" if $h{seq} eq "-";
503 $h{seqnum} = $op->seq;
504 $h{next} = $op->next;
505 $h{next} = (class($h{next}) eq "NULL") ? "(end)" : seq($h{next});
506 $h{nextaddr} = sprintf("%#x", $ {$op->next});
507 $h{sibaddr} = sprintf("%#x", $ {$op->sibling});
508 $h{firstaddr} = sprintf("%#x", $ {$op->first}) if $op->can("first");
509 $h{lastaddr} = sprintf("%#x", $ {$op->last}) if $op->can("last");
510
511 $h{classsym} = $opclass{$h{class}};
512 $h{flagval} = $op->flags;
513 $h{flags} = op_flags($op->flags);
514 $h{privval} = $op->private;
515 $h{private} = private_flags($h{name}, $op->private);
516 $h{addr} = sprintf("%#x", $$op);
517 $h{label} = $labels{$op->seq};
518 $h{typenum} = $op->type;
519 $h{noise} = $linenoise[$op->type];
78ad9108 520 $_->(\%h, $op, \$format, \$level) for @callbacks;
c99ca59a 521 return fmt_line(\%h, $format, $level);
522}
523
524sub B::OP::concise {
525 my($op, $level) = @_;
526 if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
527 my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
528 "addr" => sprintf("%#x", $$lastnext)};
529 print fmt_line($h, $gotofmt, $level+1);
530 }
531 $lastnext = $op->next;
532 print concise_op($op, $level, $format);
533}
534
31b49ad4 535# B::OP::terse (see Terse.pm) now just calls this
536sub b_terse {
537 my($op, $level) = @_;
538
539 # This isn't necessarily right, but there's no easy way to get
540 # from an OP to the right CV. This is a limitation of the
541 # ->terse() interface style, and there isn't much to do about
542 # it. In particular, we can die in concise_op if the main pad
543 # isn't long enough, or has the wrong kind of entries, compared to
544 # the pad a sub was compiled with. The fix for that would be to
545 # make a backwards compatible "terse" format that never even
546 # looked at the pad, just like the old B::Terse. I don't think
547 # that's worth the effort, though.
548 $curcv = main_cv unless $curcv;
549
550 if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
551 my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
552 "addr" => sprintf("%#x", $$lastnext)};
553 print fmt_line($h, $style{"terse"}[1], $level+1);
554 }
555 $lastnext = $op->next;
556 print concise_op($op, $level, $style{"terse"}[0]);
557}
558
c99ca59a 559sub tree {
560 my $op = shift;
561 my $level = shift;
562 my $style = $tree_decorations[$tree_style];
563 my($space, $single, $kids, $kid, $nokid, $last, $lead, $size) = @$style;
564 my $name = concise_op($op, $level, $treefmt);
565 if (not $op->flags & OPf_KIDS) {
566 return $name . "\n";
567 }
568 my @lines;
569 for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
570 push @lines, tree($kid, $level+1);
571 }
572 my $i;
573 for ($i = $#lines; substr($lines[$i], 0, 1) eq " "; $i--) {
574 $lines[$i] = $space . $lines[$i];
575 }
576 if ($i > 0) {
577 $lines[$i] = $last . $lines[$i];
578 while ($i-- > 1) {
579 if (substr($lines[$i], 0, 1) eq " ") {
580 $lines[$i] = $nokid . $lines[$i];
581 } else {
582 $lines[$i] = $kid . $lines[$i];
583 }
584 }
585 $lines[$i] = $kids . $lines[$i];
586 } else {
587 $lines[0] = $single . $lines[0];
588 }
589 return("$name$lead" . shift @lines,
590 map(" " x (length($name)+$size) . $_, @lines));
591}
592
213a1a26 593# *** Warning: fragile kludge ahead ***
594# Because the B::* modules run in the same interpreter as the code
595# they're compiling, their presence tends to distort the view we have
596# of the code we're looking at. In particular, perl gives sequence
597# numbers to both OPs in general and COPs in particular. If the
598# program we're looking at were run on its own, these numbers would
599# start at 1. Because all of B::Concise and all the modules it uses
600# are compiled first, though, by the time we get to the user's program
601# the sequence numbers are alreay at pretty high numbers, which would
602# be distracting if you're trying to tell OPs apart. Therefore we'd
603# like to subtract an offset from all the sequence numbers we display,
604# to restore the simpler view of the world. The trick is to know what
605# that offset will be, when we're still compiling B::Concise! If we
606# hardcoded a value, it would have to change every time B::Concise or
607# other modules we use do. To help a little, what we do here is
608# compile a little code at the end of the module, and compute the base
609# sequence number for the user's program as being a small offset
610# later, so all we have to worry about are changes in the offset.
c27ea44e 611# (Note that we now only play this game with COP sequence numbers. OP
612# sequence numbers aren't used to refer to OPs from a distance, and
613# they don't have much significance, so we just generate our own
614# sequence numbers which are easier to control. This way we also don't
615# stand in the way of a possible future removal of OP sequence
616# numbers).
213a1a26 617
618# When you say "perl -MO=Concise -e '$a'", the output should look like:
619
620# 4 <@> leave[t1] vKP/REFC ->(end)
621# 1 <0> enter ->2
622 #^ smallest OP sequence number should be 1
623# 2 <;> nextstate(main 1 -e:1) v ->3
624 # ^ smallest COP sequence number should be 1
625# - <1> ex-rv2sv vK/1 ->4
626# 3 <$> gvsv(*a) s ->4
627
c27ea44e 628# If the second of the marked numbers there isn't 1, it means you need
629# to update the corresponding magic number in the next line.
630# Remember, this needs to stay the last things in the module.
e69a2255 631
c27ea44e 632# Why is this different for MacOS? Does it matter?
633my $cop_seq_mnum = $^O eq 'MacOS' ? 10 : 9;
e69a2255 634$cop_seq_base = svref_2object(eval 'sub{0;}')->START->cop_seq + $cop_seq_mnum;
c99ca59a 635
6361;
637
638__END__
639
640=head1 NAME
641
642B::Concise - Walk Perl syntax tree, printing concise info about ops
643
644=head1 SYNOPSIS
645
646 perl -MO=Concise[,OPTIONS] foo.pl
647
78ad9108 648 use B::Concise qw(set_style add_callback);
649
c99ca59a 650=head1 DESCRIPTION
651
652This compiler backend prints the internal OPs of a Perl program's syntax
653tree in one of several space-efficient text formats suitable for debugging
654the inner workings of perl or other compiler backends. It can print OPs in
655the order they appear in the OP tree, in the order they will execute, or
656in a text approximation to their tree structure, and the format of the
657information displyed is customizable. Its function is similar to that of
658perl's B<-Dx> debugging flag or the B<B::Terse> module, but it is more
659sophisticated and flexible.
660
f8a679e6 661=head1 EXAMPLE
662
663Here's is a short example of output, using the default formatting
664conventions :
665
666 % perl -MO=Concise -e '$a = $b + 42'
667 8 <@> leave[t1] vKP/REFC ->(end)
668 1 <0> enter ->2
669 2 <;> nextstate(main 1 -e:1) v ->3
670 7 <2> sassign vKS/2 ->8
671 5 <2> add[t1] sK/2 ->6
672 - <1> ex-rv2sv sK/1 ->4
673 3 <$> gvsv(*b) s ->4
674 4 <$> const(IV 42) s ->5
675 - <1> ex-rv2sv sKRM*/1 ->7
676 6 <$> gvsv(*a) s ->7
677
678Each line corresponds to an operator. Null ops appear as C<ex-opname>,
679where I<opname> is the op that has been optimized away by perl.
680
681The number on the first row indicates the op's sequence number. It's
682given in base 36 by default.
683
684The symbol between angle brackets indicates the op's type : for example,
685<2> is a BINOP, <@> a LISTOP, etc. (see L</"OP class abbreviations">).
686
687The opname may be followed by op-specific information in parentheses
688(e.g. C<gvsv(*b)>), and by targ information in brackets (e.g.
689C<leave[t1]>).
690
691Next come the op flags. The common flags are listed below
692(L</"OP flags abbreviations">). The private flags follow, separated
693by a slash. For example, C<vKP/REFC> means that the leave op has
694public flags OPf_WANT_VOID, OPf_KIDS, and OPf_PARENS, and the private
695flag OPpREFCOUNTED.
696
697Finally an arrow points to the sequence number of the next op.
698
c99ca59a 699=head1 OPTIONS
700
701Arguments that don't start with a hyphen are taken to be the names of
702subroutines to print the OPs of; if no such functions are specified, the
703main body of the program (outside any subroutines, and not including use'd
704or require'd files) is printed.
705
706=over 4
707
708=item B<-basic>
709
710Print OPs in the order they appear in the OP tree (a preorder
711traversal, starting at the root). The indentation of each OP shows its
712level in the tree. This mode is the default, so the flag is included
713simply for completeness.
714
715=item B<-exec>
716
717Print OPs in the order they would normally execute (for the majority
718of constructs this is a postorder traversal of the tree, ending at the
719root). In most cases the OP that usually follows a given OP will
720appear directly below it; alternate paths are shown by indentation. In
721cases like loops when control jumps out of a linear path, a 'goto'
722line is generated.
723
724=item B<-tree>
725
726Print OPs in a text approximation of a tree, with the root of the tree
727at the left and 'left-to-right' order of children transformed into
728'top-to-bottom'. Because this mode grows both to the right and down,
729it isn't suitable for large programs (unless you have a very wide
730terminal).
731
732=item B<-compact>
733
734Use a tree format in which the minimum amount of space is used for the
735lines connecting nodes (one character in most cases). This squeezes out
736a few precious columns of screen real estate.
737
738=item B<-loose>
739
740Use a tree format that uses longer edges to separate OP nodes. This format
741tends to look better than the compact one, especially in ASCII, and is
742the default.
743
744=item B<-vt>
745
746Use tree connecting characters drawn from the VT100 line-drawing set.
747This looks better if your terminal supports it.
748
749=item B<-ascii>
750
751Draw the tree with standard ASCII characters like C<+> and C<|>. These don't
752look as clean as the VT100 characters, but they'll work with almost any
753terminal (or the horizontal scrolling mode of less(1)) and are suitable
754for text documentation or email. This is the default.
755
756=item B<-main>
757
758Include the main program in the output, even if subroutines were also
759specified.
760
761=item B<-base>I<n>
762
763Print OP sequence numbers in base I<n>. If I<n> is greater than 10, the
764digit for 11 will be 'a', and so on. If I<n> is greater than 36, the digit
765for 37 will be 'A', and so on until 62. Values greater than 62 are not
766currently supported. The default is 36.
767
768=item B<-bigendian>
769
770Print sequence numbers with the most significant digit first. This is the
771usual convention for Arabic numerals, and the default.
772
773=item B<-littleendian>
774
775Print seqence numbers with the least significant digit first.
776
777=item B<-concise>
778
779Use the author's favorite set of formatting conventions. This is the
780default, of course.
781
782=item B<-terse>
783
a6d05634 784Use formatting conventions that emulate the output of B<B::Terse>. The
c99ca59a 785basic mode is almost indistinguishable from the real B<B::Terse>, and the
786exec mode looks very similar, but is in a more logical order and lacks
787curly brackets. B<B::Terse> doesn't have a tree mode, so the tree mode
788is only vaguely reminiscient of B<B::Terse>.
789
790=item B<-linenoise>
791
792Use formatting conventions in which the name of each OP, rather than being
793written out in full, is represented by a one- or two-character abbreviation.
794This is mainly a joke.
795
796=item B<-debug>
797
798Use formatting conventions reminiscient of B<B::Debug>; these aren't
799very concise at all.
800
801=item B<-env>
802
803Use formatting conventions read from the environment variables
804C<B_CONCISE_FORMAT>, C<B_CONCISE_GOTO_FORMAT>, and C<B_CONCISE_TREE_FORMAT>.
805
806=back
807
808=head1 FORMATTING SPECIFICATIONS
809
810For each general style ('concise', 'terse', 'linenoise', etc.) there are
811three specifications: one of how OPs should appear in the basic or exec
812modes, one of how 'goto' lines should appear (these occur in the exec
813mode only), and one of how nodes should appear in tree mode. Each has the
814same format, described below. Any text that doesn't match a special
815pattern is copied verbatim.
816
817=over 4
818
819=item B<(x(>I<exec_text>B<;>I<basic_text>B<)x)>
820
821Generates I<exec_text> in exec mode, or I<basic_text> in basic mode.
822
823=item B<(*(>I<text>B<)*)>
824
825Generates one copy of I<text> for each indentation level.
826
827=item B<(*(>I<text1>B<;>I<text2>B<)*)>
828
829Generates one fewer copies of I<text1> than the indentation level, followed
830by one copy of I<text2> if the indentation level is more than 0.
831
832=item B<(?(>I<text1>B<#>I<var>I<Text2>B<)?)>
833
834If the value of I<var> is true (not empty or zero), generates the
835value of I<var> surrounded by I<text1> and I<Text2>, otherwise
836nothing.
837
838=item B<#>I<var>
839
840Generates the value of the variable I<var>.
841
842=item B<#>I<var>I<N>
843
844Generates the value of I<var>, left jutified to fill I<N> spaces.
845
846=item B<~>
847
848Any number of tildes and surrounding whitespace will be collapsed to
849a single space.
850
851=back
852
853The following variables are recognized:
854
855=over 4
856
857=item B<#addr>
858
859The address of the OP, in hexidecimal.
860
861=item B<#arg>
862
863The OP-specific information of the OP (such as the SV for an SVOP, the
864non-local exit pointers for a LOOP, etc.) enclosed in paretheses.
865
866=item B<#class>
867
868The B-determined class of the OP, in all caps.
869
f8a679e6 870=item B<#classsym>
c99ca59a 871
872A single symbol abbreviating the class of the OP.
873
c3caa09d 874=item B<#coplabel>
875
876The label of the statement or block the OP is the start of, if any.
877
c99ca59a 878=item B<#exname>
879
880The name of the OP, or 'ex-foo' if the OP is a null that used to be a foo.
881
882=item B<#extarg>
883
884The target of the OP, or nothing for a nulled OP.
885
886=item B<#firstaddr>
887
888The address of the OP's first child, in hexidecimal.
889
890=item B<#flags>
891
892The OP's flags, abbreviated as a series of symbols.
893
894=item B<#flagval>
895
896The numeric value of the OP's flags.
897
f8a679e6 898=item B<#hyphseq>
c99ca59a 899
900The sequence number of the OP, or a hyphen if it doesn't have one.
901
902=item B<#label>
903
904'NEXT', 'LAST', or 'REDO' if the OP is a target of one of those in exec
905mode, or empty otherwise.
906
907=item B<#lastaddr>
908
909The address of the OP's last child, in hexidecimal.
910
911=item B<#name>
912
913The OP's name.
914
915=item B<#NAME>
916
917The OP's name, in all caps.
918
919=item B<#next>
920
921The sequence number of the OP's next OP.
922
923=item B<#nextaddr>
924
925The address of the OP's next OP, in hexidecimal.
926
927=item B<#noise>
928
c27ea44e 929A one- or two-character abbreviation for the OP's name.
c99ca59a 930
931=item B<#private>
932
933The OP's private flags, rendered with abbreviated names if possible.
934
935=item B<#privval>
936
937The numeric value of the OP's private flags.
938
939=item B<#seq>
940
c27ea44e 941The sequence number of the OP. Note that this is now a sequence number
942generated by B::Concise, rather than the real op_seq value (for which
943see B<#seqnum>).
c99ca59a 944
945=item B<#seqnum>
946
947The real sequence number of the OP, as a regular number and not adjusted
948to be relative to the start of the real program. (This will generally be
949a fairly large number because all of B<B::Concise> is compiled before
950your program is).
951
952=item B<#sibaddr>
953
954The address of the OP's next youngest sibling, in hexidecimal.
955
956=item B<#svaddr>
957
958The address of the OP's SV, if it has an SV, in hexidecimal.
959
960=item B<#svclass>
961
962The class of the OP's SV, if it has one, in all caps (e.g., 'IV').
963
964=item B<#svval>
965
966The value of the OP's SV, if it has one, in a short human-readable format.
967
968=item B<#targ>
969
970The numeric value of the OP's targ.
971
972=item B<#targarg>
973
974The name of the variable the OP's targ refers to, if any, otherwise the
975letter t followed by the OP's targ in decimal.
976
977=item B<#targarglife>
978
979Same as B<#targarg>, but followed by the COP sequence numbers that delimit
980the variable's lifetime (or 'end' for a variable in an open scope) for a
981variable.
982
983=item B<#typenum>
984
985The numeric value of the OP's type, in decimal.
986
987=back
988
989=head1 ABBREVIATIONS
990
991=head2 OP flags abbreviations
992
993 v OPf_WANT_VOID Want nothing (void context)
994 s OPf_WANT_SCALAR Want single value (scalar context)
995 l OPf_WANT_LIST Want list of any length (list context)
996 K OPf_KIDS There is a firstborn child.
997 P OPf_PARENS This operator was parenthesized.
998 (Or block needs explicit scope entry.)
999 R OPf_REF Certified reference.
1000 (Return container, not containee).
1001 M OPf_MOD Will modify (lvalue).
1002 S OPf_STACKED Some arg is arriving on the stack.
1003 * OPf_SPECIAL Do something weird for this op (see op.h)
1004
1005=head2 OP class abbreviations
1006
1007 0 OP (aka BASEOP) An OP with no children
1008 1 UNOP An OP with one child
1009 2 BINOP An OP with two children
1010 | LOGOP A control branch OP
1011 @ LISTOP An OP that could have lots of children
1012 / PMOP An OP with a regular expression
1013 $ SVOP An OP with an SV
1014 " PVOP An OP with a string
1015 { LOOP An OP that holds pointers for a loop
1016 ; COP An OP that marks the start of a statement
051f02e9 1017 # PADOP An OP with a GV on the pad
c99ca59a 1018
78ad9108 1019=head1 Using B::Concise outside of the O framework
1020
1021It is possible to extend B<B::Concise> by using it outside of the B<O>
1022framework and providing new styles and new variables.
1023
1024 use B::Concise qw(set_style add_callback);
1025 set_style($format, $gotofmt, $treefmt);
1026 add_callback
1027 (
1028 sub
1029 {
1030 my ($h, $op, $level, $format) = @_;
1031 $h->{variable} = some_func($op);
1032 }
1033 );
1034 B::Concise::compile(@options)->();
1035
1036You can specify a style by calling the B<set_style> subroutine. If you
1037have a new variable in your style, or you want to change the value of an
1038existing variable, you will need to add a callback to specify the value
1039for that variable.
1040
1041This is done by calling B<add_callback> passing references to any
1042callback subroutines. The subroutines are called in the same order as
1043they are added. Each subroutine is passed four parameters. These are a
1044reference to a hash, the keys of which are the names of the variables
1045and the values of which are their values, the op, the level and the
1046format.
1047
1048To define your own variables, simply add them to the hash, or change
1049existing values if you need to. The level and format are passed in as
1050references to scalars, but it is unlikely that they will need to be
1051changed or even used.
1052
31b49ad4 1053To switch back to one of the standard styles like C<concise> or
1054C<terse>, use C<set_style_standard>.
1055
78ad9108 1056To see the output, call the subroutine returned by B<compile> in the
1057same way that B<O> does.
1058
c99ca59a 1059=head1 AUTHOR
1060
31b49ad4 1061Stephen McCamant, E<lt>smcc@CSUA.Berkeley.EDUE<gt>.
c99ca59a 1062
1063=cut