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