REALLY pedantic hv.h nit
[p5sagit/p5-mst-13.2.git] / ext / B / B / Concise.pm
CommitLineData
c99ca59a 1package B::Concise;
2# Copyright (C) 2000, 2001 Stephen McCamant. All rights reserved.
3# This program is free software; you can redistribute and/or modify it
4# under the same terms as Perl itself.
5
c3caa09d 6our $VERSION = "0.51";
c99ca59a 7use strict;
8use B qw(class ppname main_start main_root main_cv cstring svref_2object
9 SVf_IOK SVf_NOK SVf_POK OPf_KIDS);
10
11my %style =
12 ("terse" =>
c3caa09d 13 ["(?(#label =>\n)?)(*( )*)#class (#addr) #name (?([#targ])?) "
14 . "#svclass~(?((#svaddr))?)~#svval~(?(label \"#coplabel\")?)\n",
c99ca59a 15 "(*( )*)goto #class (#addr)\n",
16 "#class pp_#name"],
17 "concise" =>
18 ["#hyphseq2 (*( (x( ;)x))*)<#classsym> "
19 . "#exname#arg(?([#targarglife])?)~#flags(?(/#private)?)(x(;~->#next)x)\n",
20 " (*( )*) goto #seq\n",
21 "(?(<#seq>)?)#exname#arg(?([#targarglife])?)"],
22 "linenoise" =>
23 ["(x(;(*( )*))x)#noise#arg(?([#targarg])?)(x( ;\n)x)",
24 "gt_#seq ",
25 "(?(#seq)?)#noise#arg(?([#targarg])?)"],
26 "debug" =>
27 ["#class (#addr)\n\top_next\t\t#nextaddr\n\top_sibling\t#sibaddr\n\t"
28 . "op_ppaddr\tPL_ppaddr[OP_#NAME]\n\top_type\t\t#typenum\n\top_seq\t\t"
29 . "#seqnum\n\top_flags\t#flagval\n\top_private\t#privval\n"
30 . "(?(\top_first\t#firstaddr\n)?)(?(\top_last\t\t#lastaddr\n)?)"
31 . "(?(\top_sv\t\t#svaddr\n)?)",
32 " GOTO #addr\n",
33 "#addr"],
34 "env" => [$ENV{B_CONCISE_FORMAT}, $ENV{B_CONCISE_GOTO_FORMAT},
35 $ENV{B_CONCISE_TREE_FORMAT}],
36 );
37
38my($format, $gotofmt, $treefmt);
39my $curcv;
40my($seq_base, $cop_seq_base);
41
42sub concise_cv {
43 my ($order, $cvref) = @_;
44 my $cv = svref_2object($cvref);
45 $curcv = $cv;
46 if ($order eq "exec") {
47 walk_exec($cv->START);
48 } elsif ($order eq "basic") {
49 walk_topdown($cv->ROOT, sub { $_[0]->concise($_[1]) }, 0);
50 } else {
51 print tree($cv->ROOT, 0)
52 }
53}
54
55my $start_sym = "\e(0"; # "\cN" sometimes also works
56my $end_sym = "\e(B"; # "\cO" respectively
57
58my @tree_decorations =
59 ([" ", "--", "+-", "|-", "| ", "`-", "-", 1],
60 [" ", "-", "+", "+", "|", "`", "", 0],
61 [" ", map("$start_sym$_$end_sym", "qq", "wq", "tq", "x ", "mq", "q"), 1],
62 [" ", map("$start_sym$_$end_sym", "q", "w", "t", "x", "m"), "", 0],
63 );
64my $tree_style = 0;
65
66my $base = 36;
67my $big_endian = 1;
68
69my $order = "basic";
70
71sub compile {
72 my @options = grep(/^-/, @_);
73 my @args = grep(!/^-/, @_);
74 my $do_main = 0;
75 ($format, $gotofmt, $treefmt) = @{$style{"concise"}};
76 for my $o (@options) {
77 if ($o eq "-basic") {
78 $order = "basic";
79 } elsif ($o eq "-exec") {
80 $order = "exec";
81 } elsif ($o eq "-tree") {
82 $order = "tree";
83 } elsif ($o eq "-compact") {
84 $tree_style |= 1;
85 } elsif ($o eq "-loose") {
86 $tree_style &= ~1;
87 } elsif ($o eq "-vt") {
88 $tree_style |= 2;
89 } elsif ($o eq "-ascii") {
90 $tree_style &= ~2;
91 } elsif ($o eq "-main") {
92 $do_main = 1;
93 } elsif ($o =~ /^-base(\d+)$/) {
94 $base = $1;
95 } elsif ($o eq "-bigendian") {
96 $big_endian = 1;
97 } elsif ($o eq "-littleendian") {
98 $big_endian = 0;
99 } elsif (exists $style{substr($o, 1)}) {
100 ($format, $gotofmt, $treefmt) = @{$style{substr($o, 1)}};
101 } else {
102 warn "Option $o unrecognized";
103 }
104 }
105 if (@args) {
106 return sub {
107 for my $objname (@args) {
108 $objname = "main::" . $objname unless $objname =~ /::/;
109 eval "concise_cv(\$order, \\&$objname)";
110 die "concise_cv($order, \\&$objname) failed: $@" if $@;
111 }
112 }
113 }
114 if (!@args or $do_main) {
115 if ($order eq "exec") {
116 return sub { return if class(main_start) eq "NULL";
117 $curcv = main_cv;
118 walk_exec(main_start) }
119 } elsif ($order eq "tree") {
120 return sub { return if class(main_root) eq "NULL";
121 $curcv = main_cv;
122 print tree(main_root, 0) }
123 } elsif ($order eq "basic") {
124 return sub { return if class(main_root) eq "NULL";
125 $curcv = main_cv;
126 walk_topdown(main_root,
127 sub { $_[0]->concise($_[1]) }, 0); }
128 }
129 }
130}
131
132my %labels;
133my $lastnext;
134
135my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
136 'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
137 'PVOP' => '"', 'LOOP' => "{", 'COP' => ";");
138
139my @linenoise =
140 qw'# () sc ( @? 1 $* gv *{ m$ m@ m% m? p/ *$ $ $# & a& pt \\ s\\ rf bl
141 ` *? <> ?? ?/ r/ c/ // qr s/ /c y/ = @= C sC Cp sp df un BM po +1 +I
142 -1 -I 1+ I+ 1- I- ** * i* / i/ %$ i% x + i+ - i- . " << >> < i<
143 > i> <= i, >= i. == i= != i! <? i? s< s> s, s. s= s! s? b& b^ b| -0 -i
144 ! ~ a2 si cs rd sr e^ lg sq in %x %o ab le ss ve ix ri sf FL od ch cy
145 uf lf uc lc qm @ [f [ @[ eh vl ky dl ex % ${ @{ uk pk st jn ) )[ a@
146 a% sl +] -] [- [+ so rv GS GW MS MW .. f. .f && || ^^ ?: &= |= -> s{ s}
147 v} ca wa di rs ;; ; ;d }{ { } {} f{ it {l l} rt }l }n }r dm }g }e ^o
148 ^c ^| ^# um bm t~ u~ ~d DB db ^s se ^g ^r {w }w pf pr ^O ^K ^R ^W ^d ^v
149 ^e ^t ^k t. fc ic fl .s .p .b .c .l .a .h g1 s1 g2 s2 ?. l? -R -W -X -r
150 -w -x -e -o -O -z -s -M -A -C -S -c -b -f -d -p -l -u -g -k -t -T -B cd
151 co cr u. cm ut r. l@ s@ r@ mD uD oD rD tD sD wD cD f$ w$ p$ sh e$ k$ g3
152 g4 s4 g5 s5 T@ C@ L@ G@ A@ S@ Hg Hc Hr Hw Mg Mc Ms Mr Sg Sc So rq do {e
153 e} {t t} g6 G6 6e g7 G7 7e g8 G8 8e g9 G9 9e 6s 7s 8s 9s 6E 7E 8E 9E Pn
154 Pu GP SP EP Gn Gg GG SG EG g0 c$ lk t$ ;s n>';
155
156my $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
157
158sub op_flags {
159 my($x) = @_;
160 my(@v);
161 push @v, "v" if ($x & 3) == 1;
162 push @v, "s" if ($x & 3) == 2;
163 push @v, "l" if ($x & 3) == 3;
164 push @v, "K" if $x & 4;
165 push @v, "P" if $x & 8;
166 push @v, "R" if $x & 16;
167 push @v, "M" if $x & 32;
168 push @v, "S" if $x & 64;
169 push @v, "*" if $x & 128;
170 return join("", @v);
171}
172
173sub base_n {
174 my $x = shift;
175 return "-" . base_n(-$x) if $x < 0;
176 my $str = "";
177 do { $str .= substr($chars, $x % $base, 1) } while $x = int($x / $base);
178 $str = reverse $str if $big_endian;
179 return $str;
180}
181
182sub seq { return $_[0]->seq ? base_n($_[0]->seq - $seq_base) : "-" }
183
184sub walk_topdown {
185 my($op, $sub, $level) = @_;
186 $sub->($op, $level);
187 if ($op->flags & OPf_KIDS) {
188 for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
189 walk_topdown($kid, $sub, $level + 1);
190 }
191 }
192 if (class($op) eq "PMOP" and $ {$op->pmreplroot}) {
193 walk_topdown($op->pmreplroot, $sub, $level + 1);
194 }
195}
196
197sub walklines {
198 my($ar, $level) = @_;
199 for my $l (@$ar) {
200 if (ref($l) eq "ARRAY") {
201 walklines($l, $level + 1);
202 } else {
203 $l->concise($level);
204 }
205 }
206}
207
208sub walk_exec {
209 my($top, $level) = @_;
210 my %opsseen;
211 my @lines;
212 my @todo = ([$top, \@lines]);
213 while (@todo and my($op, $targ) = @{shift @todo}) {
214 for (; $$op; $op = $op->next) {
215 last if $opsseen{$$op}++;
216 push @$targ, $op;
217 my $name = $op->name;
218 if ($name
219 =~ /^(or|and|(map|grep)while|entertry|range|cond_expr)$/) {
220 my $ar = [];
221 push @$targ, $ar;
222 push @todo, [$op->other, $ar];
223 } elsif ($name eq "subst" and $ {$op->pmreplstart}) {
224 my $ar = [];
225 push @$targ, $ar;
226 push @todo, [$op->pmreplstart, $ar];
227 } elsif ($name =~ /^enter(loop|iter)$/) {
228 $labels{$op->nextop->seq} = "NEXT";
229 $labels{$op->lastop->seq} = "LAST";
230 $labels{$op->redoop->seq} = "REDO";
231 }
232 }
233 }
234 walklines(\@lines, 0);
235}
236
237sub fmt_line {
238 my($hr, $fmt, $level) = @_;
239 my $text = $fmt;
240 $text =~ s/\(\?\(([^\#]*?)\#(\w+)([^\#]*?)\)\?\)/
241 $hr->{$2} ? $1.$hr->{$2}.$3 : ""/eg;
242 $text =~ s/\(x\((.*?);(.*?)\)x\)/$order eq "exec" ? $1 : $2/egs;
243 $text =~ s/\(\*\(([^;]*?)\)\*\)/$1 x $level/egs;
244 $text =~ s/\(\*\((.*?);(.*?)\)\*\)/$1 x ($level - 1) . $2 x ($level>0)/egs;
245 $text =~ s/#([a-zA-Z]+)(\d+)/sprintf("%-$2s", $hr->{$1})/eg;
246 $text =~ s/#([a-zA-Z]+)/$hr->{$1}/eg;
247 $text =~ s/[ \t]*~+[ \t]*/ /g;
248 return $text;
249}
250
251my %priv;
252$priv{$_}{128} = "LVINTRO"
253 for ("pos", "substr", "vec", "threadsv", "gvsv", "rv2sv", "rv2hv", "rv2gv",
254 "rv2av", "rv2arylen", "aelem", "helem", "aslice", "hslice", "padsv",
255 "padav", "padhv");
256$priv{$_}{64} = "REFC" for ("leave", "leavesub", "leavesublv", "leavewrite");
257$priv{"aassign"}{64} = "COMMON";
258$priv{"aassign"}{32} = "PHASH";
259$priv{"sassign"}{64} = "BKWARD";
260$priv{$_}{64} = "RTIME" for ("match", "subst", "substcont");
261@{$priv{"trans"}}{1,2,4,8,16,64} = ("<UTF", ">UTF", "IDENT", "SQUASH", "DEL",
262 "COMPL", "GROWS");
263$priv{"repeat"}{64} = "DOLIST";
264$priv{"leaveloop"}{64} = "CONT";
265@{$priv{$_}}{32,64,96} = ("DREFAV", "DREFHV", "DREFSV")
266 for ("entersub", map("rv2${_}v", "a", "s", "h", "g"), "aelem", "helem");
267$priv{"entersub"}{16} = "DBG";
268$priv{"entersub"}{32} = "TARG";
269@{$priv{$_}}{4,8,128} = ("INARGS","AMPER","NO()") for ("entersub", "rv2cv");
270$priv{"gv"}{32} = "EARLYCV";
271$priv{"aelem"}{16} = $priv{"helem"}{16} = "LVDEFER";
272$priv{$_}{16} = "OURINTR" for ("gvsv", "rv2sv", "rv2av", "rv2hv", "r2gv");
273$priv{$_}{16} = "TARGMY"
274 for (map(($_,"s$_"),"chop", "chomp"),
275 map(($_,"i_$_"), "postinc", "postdec", "multiply", "divide", "modulo",
276 "add", "subtract", "negate"), "pow", "concat", "stringify",
277 "left_shift", "right_shift", "bit_and", "bit_xor", "bit_or",
278 "complement", "atan2", "sin", "cos", "rand", "exp", "log", "sqrt",
279 "int", "hex", "oct", "abs", "length", "index", "rindex", "sprintf",
280 "ord", "chr", "crypt", "quotemeta", "join", "push", "unshift", "flock",
281 "chdir", "chown", "chroot", "unlink", "chmod", "utime", "rename",
282 "link", "symlink", "mkdir", "rmdir", "wait", "waitpid", "system",
283 "exec", "kill", "getppid", "getpgrp", "setpgrp", "getpriority",
284 "setpriority", "time", "sleep");
285@{$priv{"const"}}{8,16,32,64,128} = ("STRICT","ENTERED", "$[", "BARE", "WARN");
286$priv{"flip"}{64} = $priv{"flop"}{64} = "LINENUM";
287$priv{"list"}{64} = "GUESSED";
288$priv{"delete"}{64} = "SLICE";
289$priv{"exists"}{64} = "SUB";
290$priv{$_}{64} = "LOCALE"
291 for ("sort", "prtf", "sprintf", "slt", "sle", "seq", "sne", "sgt", "sge",
292 "scmp", "lc", "uc", "lcfirst", "ucfirst");
293@{$priv{"sort"}}{1,2,4} = ("NUM", "INT", "REV");
294$priv{"threadsv"}{64} = "SVREFd";
295$priv{$_}{16} = "INBIN" for ("open", "backtick");
296$priv{$_}{32} = "INCR" for ("open", "backtick");
297$priv{$_}{64} = "OUTBIN" for ("open", "backtick");
298$priv{$_}{128} = "OUTCR" for ("open", "backtick");
299$priv{"exit"}{128} = "VMS";
300
301sub private_flags {
302 my($name, $x) = @_;
303 my @s;
304 for my $flag (128, 96, 64, 32, 16, 8, 4, 2, 1) {
305 if ($priv{$name}{$flag} and $x & $flag and $x >= $flag) {
306 $x -= $flag;
307 push @s, $priv{$name}{$flag};
308 }
309 }
310 push @s, $x if $x;
311 return join(",", @s);
312}
313
314sub concise_op {
315 my ($op, $level, $format) = @_;
316 my %h;
317 $h{exname} = $h{name} = $op->name;
318 $h{NAME} = uc $h{name};
319 $h{class} = class($op);
320 $h{extarg} = $h{targ} = $op->targ;
321 $h{extarg} = "" unless $h{extarg};
322 if ($h{name} eq "null" and $h{targ}) {
323 $h{exname} = "ex-" . substr(ppname($h{targ}), 3);
324 $h{extarg} = "";
325 } elsif ($h{targ}) {
326 my $padname = (($curcv->PADLIST->ARRAY)[0]->ARRAY)[$h{targ}];
327 if (defined $padname and class($padname) ne "SPECIAL") {
328 $h{targarg} = $padname->PV;
329 my $intro = $padname->NVX - $cop_seq_base;
330 my $finish = int($padname->IVX) - $cop_seq_base;
331 $finish = "end" if $finish == 999999999 - $cop_seq_base;
332 $h{targarglife} = "$h{targarg}:$intro,$finish";
333 } else {
334 $h{targarglife} = $h{targarg} = "t" . $h{targ};
335 }
336 }
337 $h{arg} = "";
338 $h{svclass} = $h{svaddr} = $h{svval} = "";
339 if ($h{class} eq "PMOP") {
340 my $precomp = $op->precomp;
341 $precomp = defined($precomp) ? "/$precomp/" : "";
342 my $pmreplstart;
343 if ($ {$op->pmreplstart}) {
344 undef $lastnext;
345 $pmreplstart = "replstart->" . seq($op->pmreplstart);
346 $h{arg} = "(" . join(" ", $precomp, $pmreplstart) . ")";
347 } else {
348 $h{arg} = "($precomp)";
349 }
350 } elsif ($h{class} eq "PVOP" and $h{name} ne "trans") {
351 $h{arg} = '("' . $op->pv . '")';
352 $h{svval} = '"' . $op->pv . '"';
353 } elsif ($h{class} eq "COP") {
354 my $label = $op->label;
c3caa09d 355 $h{coplabel} = $label;
c99ca59a 356 $label = $label ? "$label: " : "";
357 my $loc = $op->file;
358 $loc =~ s[.*/][];
359 $loc .= ":" . $op->line;
360 my($stash, $cseq) = ($op->stash->NAME, $op->cop_seq - $cop_seq_base);
361 my $arybase = $op->arybase;
362 $arybase = $arybase ? ' $[=' . $arybase : "";
363 $h{arg} = "($label$stash $cseq $loc$arybase)";
364 } elsif ($h{class} eq "LOOP") {
365 $h{arg} = "(next->" . seq($op->nextop) . " last->" . seq($op->lastop)
366 . " redo->" . seq($op->redoop) . ")";
367 } elsif ($h{class} eq "LOGOP") {
368 undef $lastnext;
369 $h{arg} = "(other->" . seq($op->other) . ")";
370 } elsif ($h{class} eq "SVOP") {
371 my $sv = $op->sv;
372 $h{svclass} = class($sv);
373 $h{svaddr} = sprintf("%#x", $$sv);
374 if ($h{svclass} eq "GV") {
375 my $gv = $sv;
376 my $stash = $gv->STASH->NAME;
377 if ($stash eq "main") {
378 $stash = "";
379 } else {
380 $stash = $stash . "::";
381 }
382 $h{arg} = "(*$stash" . $gv->NAME . ")";
383 $h{svval} = "*$stash" . $gv->NAME;
384 } else {
385 while (class($sv) eq "RV") {
386 $h{svval} .= "\\";
387 $sv = $sv->RV;
388 }
389 if (class($sv) eq "SPECIAL") {
390 $h{svval} = ["Null", "sv_undef", "sv_yes", "sv_no"]->[$$sv];
391 } elsif ($sv->FLAGS & SVf_NOK) {
392 $h{svval} = $sv->NV;
393 } elsif ($sv->FLAGS & SVf_IOK) {
394 $h{svval} = $sv->IV;
395 } elsif ($sv->FLAGS & SVf_POK) {
396 $h{svval} = cstring($sv->PV);
397 }
398 $h{arg} = "($h{svclass} $h{svval})";
399 }
400 }
401 $h{seq} = $h{hyphseq} = seq($op);
402 $h{seq} = "" if $h{seq} eq "-";
403 $h{seqnum} = $op->seq;
404 $h{next} = $op->next;
405 $h{next} = (class($h{next}) eq "NULL") ? "(end)" : seq($h{next});
406 $h{nextaddr} = sprintf("%#x", $ {$op->next});
407 $h{sibaddr} = sprintf("%#x", $ {$op->sibling});
408 $h{firstaddr} = sprintf("%#x", $ {$op->first}) if $op->can("first");
409 $h{lastaddr} = sprintf("%#x", $ {$op->last}) if $op->can("last");
410
411 $h{classsym} = $opclass{$h{class}};
412 $h{flagval} = $op->flags;
413 $h{flags} = op_flags($op->flags);
414 $h{privval} = $op->private;
415 $h{private} = private_flags($h{name}, $op->private);
416 $h{addr} = sprintf("%#x", $$op);
417 $h{label} = $labels{$op->seq};
418 $h{typenum} = $op->type;
419 $h{noise} = $linenoise[$op->type];
420 return fmt_line(\%h, $format, $level);
421}
422
423sub B::OP::concise {
424 my($op, $level) = @_;
425 if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
426 my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
427 "addr" => sprintf("%#x", $$lastnext)};
428 print fmt_line($h, $gotofmt, $level+1);
429 }
430 $lastnext = $op->next;
431 print concise_op($op, $level, $format);
432}
433
434sub tree {
435 my $op = shift;
436 my $level = shift;
437 my $style = $tree_decorations[$tree_style];
438 my($space, $single, $kids, $kid, $nokid, $last, $lead, $size) = @$style;
439 my $name = concise_op($op, $level, $treefmt);
440 if (not $op->flags & OPf_KIDS) {
441 return $name . "\n";
442 }
443 my @lines;
444 for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
445 push @lines, tree($kid, $level+1);
446 }
447 my $i;
448 for ($i = $#lines; substr($lines[$i], 0, 1) eq " "; $i--) {
449 $lines[$i] = $space . $lines[$i];
450 }
451 if ($i > 0) {
452 $lines[$i] = $last . $lines[$i];
453 while ($i-- > 1) {
454 if (substr($lines[$i], 0, 1) eq " ") {
455 $lines[$i] = $nokid . $lines[$i];
456 } else {
457 $lines[$i] = $kid . $lines[$i];
458 }
459 }
460 $lines[$i] = $kids . $lines[$i];
461 } else {
462 $lines[0] = $single . $lines[0];
463 }
464 return("$name$lead" . shift @lines,
465 map(" " x (length($name)+$size) . $_, @lines));
466}
467
468# This is a bit of a hack; the 2 and 15 were determined empirically.
469# These need to stay the last things in the module.
470$cop_seq_base = svref_2object(eval 'sub{0;}')->START->cop_seq + 2;
471$seq_base = svref_2object(eval 'sub{}')->START->seq + 15;
472
4731;
474
475__END__
476
477=head1 NAME
478
479B::Concise - Walk Perl syntax tree, printing concise info about ops
480
481=head1 SYNOPSIS
482
483 perl -MO=Concise[,OPTIONS] foo.pl
484
485=head1 DESCRIPTION
486
487This compiler backend prints the internal OPs of a Perl program's syntax
488tree in one of several space-efficient text formats suitable for debugging
489the inner workings of perl or other compiler backends. It can print OPs in
490the order they appear in the OP tree, in the order they will execute, or
491in a text approximation to their tree structure, and the format of the
492information displyed is customizable. Its function is similar to that of
493perl's B<-Dx> debugging flag or the B<B::Terse> module, but it is more
494sophisticated and flexible.
495
496=head1 OPTIONS
497
498Arguments that don't start with a hyphen are taken to be the names of
499subroutines to print the OPs of; if no such functions are specified, the
500main body of the program (outside any subroutines, and not including use'd
501or require'd files) is printed.
502
503=over 4
504
505=item B<-basic>
506
507Print OPs in the order they appear in the OP tree (a preorder
508traversal, starting at the root). The indentation of each OP shows its
509level in the tree. This mode is the default, so the flag is included
510simply for completeness.
511
512=item B<-exec>
513
514Print OPs in the order they would normally execute (for the majority
515of constructs this is a postorder traversal of the tree, ending at the
516root). In most cases the OP that usually follows a given OP will
517appear directly below it; alternate paths are shown by indentation. In
518cases like loops when control jumps out of a linear path, a 'goto'
519line is generated.
520
521=item B<-tree>
522
523Print OPs in a text approximation of a tree, with the root of the tree
524at the left and 'left-to-right' order of children transformed into
525'top-to-bottom'. Because this mode grows both to the right and down,
526it isn't suitable for large programs (unless you have a very wide
527terminal).
528
529=item B<-compact>
530
531Use a tree format in which the minimum amount of space is used for the
532lines connecting nodes (one character in most cases). This squeezes out
533a few precious columns of screen real estate.
534
535=item B<-loose>
536
537Use a tree format that uses longer edges to separate OP nodes. This format
538tends to look better than the compact one, especially in ASCII, and is
539the default.
540
541=item B<-vt>
542
543Use tree connecting characters drawn from the VT100 line-drawing set.
544This looks better if your terminal supports it.
545
546=item B<-ascii>
547
548Draw the tree with standard ASCII characters like C<+> and C<|>. These don't
549look as clean as the VT100 characters, but they'll work with almost any
550terminal (or the horizontal scrolling mode of less(1)) and are suitable
551for text documentation or email. This is the default.
552
553=item B<-main>
554
555Include the main program in the output, even if subroutines were also
556specified.
557
558=item B<-base>I<n>
559
560Print OP sequence numbers in base I<n>. If I<n> is greater than 10, the
561digit for 11 will be 'a', and so on. If I<n> is greater than 36, the digit
562for 37 will be 'A', and so on until 62. Values greater than 62 are not
563currently supported. The default is 36.
564
565=item B<-bigendian>
566
567Print sequence numbers with the most significant digit first. This is the
568usual convention for Arabic numerals, and the default.
569
570=item B<-littleendian>
571
572Print seqence numbers with the least significant digit first.
573
574=item B<-concise>
575
576Use the author's favorite set of formatting conventions. This is the
577default, of course.
578
579=item B<-terse>
580
581Use formatting conventions that emulate the ouput of B<B::Terse>. The
582basic mode is almost indistinguishable from the real B<B::Terse>, and the
583exec mode looks very similar, but is in a more logical order and lacks
584curly brackets. B<B::Terse> doesn't have a tree mode, so the tree mode
585is only vaguely reminiscient of B<B::Terse>.
586
587=item B<-linenoise>
588
589Use formatting conventions in which the name of each OP, rather than being
590written out in full, is represented by a one- or two-character abbreviation.
591This is mainly a joke.
592
593=item B<-debug>
594
595Use formatting conventions reminiscient of B<B::Debug>; these aren't
596very concise at all.
597
598=item B<-env>
599
600Use formatting conventions read from the environment variables
601C<B_CONCISE_FORMAT>, C<B_CONCISE_GOTO_FORMAT>, and C<B_CONCISE_TREE_FORMAT>.
602
603=back
604
605=head1 FORMATTING SPECIFICATIONS
606
607For each general style ('concise', 'terse', 'linenoise', etc.) there are
608three specifications: one of how OPs should appear in the basic or exec
609modes, one of how 'goto' lines should appear (these occur in the exec
610mode only), and one of how nodes should appear in tree mode. Each has the
611same format, described below. Any text that doesn't match a special
612pattern is copied verbatim.
613
614=over 4
615
616=item B<(x(>I<exec_text>B<;>I<basic_text>B<)x)>
617
618Generates I<exec_text> in exec mode, or I<basic_text> in basic mode.
619
620=item B<(*(>I<text>B<)*)>
621
622Generates one copy of I<text> for each indentation level.
623
624=item B<(*(>I<text1>B<;>I<text2>B<)*)>
625
626Generates one fewer copies of I<text1> than the indentation level, followed
627by one copy of I<text2> if the indentation level is more than 0.
628
629=item B<(?(>I<text1>B<#>I<var>I<Text2>B<)?)>
630
631If the value of I<var> is true (not empty or zero), generates the
632value of I<var> surrounded by I<text1> and I<Text2>, otherwise
633nothing.
634
635=item B<#>I<var>
636
637Generates the value of the variable I<var>.
638
639=item B<#>I<var>I<N>
640
641Generates the value of I<var>, left jutified to fill I<N> spaces.
642
643=item B<~>
644
645Any number of tildes and surrounding whitespace will be collapsed to
646a single space.
647
648=back
649
650The following variables are recognized:
651
652=over 4
653
654=item B<#addr>
655
656The address of the OP, in hexidecimal.
657
658=item B<#arg>
659
660The OP-specific information of the OP (such as the SV for an SVOP, the
661non-local exit pointers for a LOOP, etc.) enclosed in paretheses.
662
663=item B<#class>
664
665The B-determined class of the OP, in all caps.
666
667=item B<#classym>
668
669A single symbol abbreviating the class of the OP.
670
c3caa09d 671=item B<#coplabel>
672
673The label of the statement or block the OP is the start of, if any.
674
c99ca59a 675=item B<#exname>
676
677The name of the OP, or 'ex-foo' if the OP is a null that used to be a foo.
678
679=item B<#extarg>
680
681The target of the OP, or nothing for a nulled OP.
682
683=item B<#firstaddr>
684
685The address of the OP's first child, in hexidecimal.
686
687=item B<#flags>
688
689The OP's flags, abbreviated as a series of symbols.
690
691=item B<#flagval>
692
693The numeric value of the OP's flags.
694
695=item B<#hyphenseq>
696
697The sequence number of the OP, or a hyphen if it doesn't have one.
698
699=item B<#label>
700
701'NEXT', 'LAST', or 'REDO' if the OP is a target of one of those in exec
702mode, or empty otherwise.
703
704=item B<#lastaddr>
705
706The address of the OP's last child, in hexidecimal.
707
708=item B<#name>
709
710The OP's name.
711
712=item B<#NAME>
713
714The OP's name, in all caps.
715
716=item B<#next>
717
718The sequence number of the OP's next OP.
719
720=item B<#nextaddr>
721
722The address of the OP's next OP, in hexidecimal.
723
724=item B<#noise>
725
726The two-character abbreviation for the OP's name.
727
728=item B<#private>
729
730The OP's private flags, rendered with abbreviated names if possible.
731
732=item B<#privval>
733
734The numeric value of the OP's private flags.
735
736=item B<#seq>
737
738The sequence number of the OP.
739
740=item B<#seqnum>
741
742The real sequence number of the OP, as a regular number and not adjusted
743to be relative to the start of the real program. (This will generally be
744a fairly large number because all of B<B::Concise> is compiled before
745your program is).
746
747=item B<#sibaddr>
748
749The address of the OP's next youngest sibling, in hexidecimal.
750
751=item B<#svaddr>
752
753The address of the OP's SV, if it has an SV, in hexidecimal.
754
755=item B<#svclass>
756
757The class of the OP's SV, if it has one, in all caps (e.g., 'IV').
758
759=item B<#svval>
760
761The value of the OP's SV, if it has one, in a short human-readable format.
762
763=item B<#targ>
764
765The numeric value of the OP's targ.
766
767=item B<#targarg>
768
769The name of the variable the OP's targ refers to, if any, otherwise the
770letter t followed by the OP's targ in decimal.
771
772=item B<#targarglife>
773
774Same as B<#targarg>, but followed by the COP sequence numbers that delimit
775the variable's lifetime (or 'end' for a variable in an open scope) for a
776variable.
777
778=item B<#typenum>
779
780The numeric value of the OP's type, in decimal.
781
782=back
783
784=head1 ABBREVIATIONS
785
786=head2 OP flags abbreviations
787
788 v OPf_WANT_VOID Want nothing (void context)
789 s OPf_WANT_SCALAR Want single value (scalar context)
790 l OPf_WANT_LIST Want list of any length (list context)
791 K OPf_KIDS There is a firstborn child.
792 P OPf_PARENS This operator was parenthesized.
793 (Or block needs explicit scope entry.)
794 R OPf_REF Certified reference.
795 (Return container, not containee).
796 M OPf_MOD Will modify (lvalue).
797 S OPf_STACKED Some arg is arriving on the stack.
798 * OPf_SPECIAL Do something weird for this op (see op.h)
799
800=head2 OP class abbreviations
801
802 0 OP (aka BASEOP) An OP with no children
803 1 UNOP An OP with one child
804 2 BINOP An OP with two children
805 | LOGOP A control branch OP
806 @ LISTOP An OP that could have lots of children
807 / PMOP An OP with a regular expression
808 $ SVOP An OP with an SV
809 " PVOP An OP with a string
810 { LOOP An OP that holds pointers for a loop
811 ; COP An OP that marks the start of a statement
812
813=head1 AUTHOR
814
815Stephen McCamant, C<smcc@CSUA.Berkeley.EDU>
816
817=cut