summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/perl/ext/B
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-08-09 18:10:42 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-08-09 18:10:42 +0000
commitb30707e4885ca231ff72a496671faa7830e8002a (patch)
treeceefb7d8635e495c31ba663e183cdcad8a9b157c /gnu/usr.bin/perl/ext/B
parent3c5182ca6f3c3cb0d292743e65788c0b1d03b596 (diff)
merge 5.8.5 into HEAD
remove now-unused files crank libperl shared library major number update Makefile.bsd-wrapper tweak openbsd hints file for arm and m68k
Diffstat (limited to 'gnu/usr.bin/perl/ext/B')
-rw-r--r--gnu/usr.bin/perl/ext/B/B/Concise.pm451
1 files changed, 343 insertions, 108 deletions
diff --git a/gnu/usr.bin/perl/ext/B/B/Concise.pm b/gnu/usr.bin/perl/ext/B/B/Concise.pm
index 7a24f366085..88a31b63873 100644
--- a/gnu/usr.bin/perl/ext/B/B/Concise.pm
+++ b/gnu/usr.bin/perl/ext/B/B/Concise.pm
@@ -14,16 +14,20 @@ use warnings; # uses #3 and #4, since warnings uses Carp
use Exporter (); # use #5
-our $VERSION = "0.56";
+# Maint doesn't have patch 22353 (op_seq changes)
+
+our $VERSION = "0.61";
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(set_style set_style_standard add_callback
- concise_subref concise_cv concise_main);
+ concise_subref concise_cv concise_main
+ add_style walk_output);
# use #6
use B qw(class ppname main_start main_root main_cv cstring svref_2object
- SVf_IOK SVf_NOK SVf_POK SVf_IVisUV SVf_FAKE OPf_KIDS CVf_ANON);
+ SVf_IOK SVf_NOK SVf_POK SVf_IVisUV SVf_FAKE OPf_KIDS OPf_SPECIAL
+ CVf_ANON);
-my %style =
+my %style =
("terse" =>
["(?(#label =>\n)?)(*( )*)#class (#addr) #name (?([#targ])?) "
. "#svclass~(?((#svaddr))?)~#svval~(?(label \"#coplabel\")?)\n",
@@ -50,27 +54,77 @@ my %style =
$ENV{B_CONCISE_TREE_FORMAT}],
);
-my($format, $gotofmt, $treefmt);
+# Renderings, ie how Concise prints, is controlled by these vars
+# primary:
+our $stylename; # selects current style from %style
+my $order = "basic"; # how optree is walked & printed: basic, exec, tree
+
+# rendering mechanics:
+# these 'formats' are the line-rendering templates
+# they're updated from %style when $stylename changes
+my ($format, $gotofmt, $treefmt);
+
+# lesser players:
+my $base = 36; # how <sequence#> is displayed
+my $big_endian = 1; # more <sequence#> display
+my $tree_style = 0; # tree-order details
+my $banner = 1; # print banner before optree is traversed
+
+# another factor:
+our @callbacks; # allow external management
+
+set_style_standard("concise");
+
my $curcv;
my $cop_seq_base;
-my @callbacks;
sub set_style {
($format, $gotofmt, $treefmt) = @_;
+ #warn "set_style: deprecated, use set_style_standard instead\n"; # someday
+ die "expecting 3 style-format args\n" unless @_ == 3;
+}
+
+sub add_style {
+ my ($newstyle,@args) = @_;
+ die "style '$newstyle' already exists, choose a new name\n"
+ if exists $style{$newstyle};
+ die "expecting 3 style-format args\n" unless @args == 3;
+ $style{$newstyle} = [@args];
+ $stylename = $newstyle; # update rendering state
}
sub set_style_standard {
- my($name) = @_;
- set_style(@{$style{$name}});
+ ($stylename) = @_; # update rendering state
+ die "err: style '$stylename' unknown\n" unless exists $style{$stylename};
+ set_style(@{$style{$stylename}});
}
sub add_callback {
push @callbacks, @_;
}
+# output handle, used with all Concise-output printing
+our $walkHandle = \*STDOUT; # public for your convenience
+
+sub walk_output { # updates $walkHandle
+ my $handle = shift;
+ if (ref $handle eq 'SCALAR') {
+ # in 5.8+, open(FILEHANDLE,MODE,REFERENCE) writes to string
+ open my $tmp, '>', $handle; # but cant re-set an existing filehandle
+ $walkHandle = $tmp; # so use my $tmp as intermediate var
+ return;
+ }
+ $walkHandle = $handle;
+ my $iotype = ref $walkHandle;
+ die "expecting argument/object that can print\n"
+ unless $iotype eq 'GLOB' or $iotype and $walkHandle->can('print');
+}
+
sub concise_subref {
- my($order, $subref) = @_;
- concise_cv_obj($order, svref_2object($subref));
+ my($order, $coderef) = @_;
+ my $codeobj = svref_2object($coderef);
+ die "err: not a coderef: $coderef\n" unless ref $codeobj eq 'B::CV';#CODE';
+ concise_cv_obj($order, $codeobj);
}
# This should have been called concise_subref, but it was exported
@@ -80,13 +134,14 @@ sub concise_cv { concise_subref(@_); }
sub concise_cv_obj {
my ($order, $cv) = @_;
$curcv = $cv;
+ die "err: coderef has no START\n" if class($cv->START) eq "NULL";
sequence($cv->START);
if ($order eq "exec") {
walk_exec($cv->START);
} elsif ($order eq "basic") {
walk_topdown($cv->ROOT, sub { $_[0]->concise($_[1]) }, 0);
} else {
- print tree($cv->ROOT, 0)
+ print $walkHandle tree($cv->ROOT, 0);
}
}
@@ -99,7 +154,7 @@ sub concise_main {
walk_exec(main_start);
} elsif ($order eq "tree") {
return if class(main_root) eq "NULL";
- print tree(main_root, 0);
+ print $walkHandle tree(main_root, 0);
} elsif ($order eq "basic") {
return if class(main_root) eq "NULL";
walk_topdown(main_root,
@@ -115,8 +170,8 @@ sub concise_specials {
} elsif ($name eq "CHECK") {
pop @cv_s; # skip the CHECK block that calls us
}
- for my $cv (@cv_s) {
- print "$name $i:\n";
+ for my $cv (@cv_s) {
+ print $walkHandle "$name $i:\n";
$i++;
concise_cv_obj($order, $cv);
}
@@ -125,20 +180,12 @@ sub concise_specials {
my $start_sym = "\e(0"; # "\cN" sometimes also works
my $end_sym = "\e(B"; # "\cO" respectively
-my @tree_decorations =
+my @tree_decorations =
([" ", "--", "+-", "|-", "| ", "`-", "-", 1],
[" ", "-", "+", "+", "|", "`", "", 0],
[" ", map("$start_sym$_$end_sym", "qq", "wq", "tq", "x ", "mq", "q"), 1],
[" ", map("$start_sym$_$end_sym", "q", "w", "t", "x", "m"), "", 0],
);
-my $tree_style = 0;
-
-my $base = 36;
-my $big_endian = 1;
-
-my $order = "basic";
-
-set_style_standard("concise");
sub compile {
my @options = grep(/^-/, @_);
@@ -167,8 +214,12 @@ sub compile {
$big_endian = 1;
} elsif ($o eq "-littleendian") {
$big_endian = 0;
- } elsif (exists $style{substr($o, 1)}) {
- set_style(@{$style{substr($o, 1)}});
+ } elsif ($o eq "-banner") {
+ $banner = 0;
+ }
+ elsif (exists $style{substr($o, 1)}) {
+ $stylename = substr($o, 1);
+ set_style_standard($stylename);
} else {
warn "Option $o unrecognized";
}
@@ -193,22 +244,33 @@ sub compile {
B::end_av->isa("B::AV") ?
B::end_av->ARRAY : ());
} else {
- $objname = "main::" . $objname unless $objname =~ /::/;
- print "$objname:\n";
- eval "concise_subref(\$order, \\&$objname)";
- die "concise_subref($order, \\&$objname) failed: $@" if $@;
+ # convert function names to subrefs
+ my $objref;
+ if (ref $objname) {
+ print $walkHandle "B::Concise::compile($objname)\n"
+ if $banner;
+ $objref = $objname;
+ } else {
+ $objname = "main::" . $objname unless $objname =~ /::/;
+ print $walkHandle "$objname:\n";
+ no strict 'refs';
+ die "err: unknown function ($objname)\n"
+ unless *{$objname}{CODE};
+ $objref = \&$objname;
+ }
+ concise_subref($order, $objref);
}
}
}
if (!@args or $do_main) {
- print "main program:\n" if $do_main;
+ print $walkHandle "main program:\n" if $do_main;
concise_main($order);
}
}
}
my %labels;
-my $lastnext;
+my $lastnext; # remembers op-chain, used to insert gotos
my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
@@ -261,6 +323,12 @@ sub base_n {
my %sequence_num;
my $seq_max = 1;
+sub reset_sequence {
+ # reset the sequence
+ %sequence_num = ();
+ $seq_max = 1;
+}
+
sub seq {
my($op) = @_;
return "-" if not exists $sequence_num{$$op};
@@ -360,18 +428,23 @@ sub sequence {
}
}
-sub fmt_line {
- my($hr, $fmt, $level) = @_;
- my $text = $fmt;
+sub fmt_line { # generate text-line for op.
+ my($hr, $text, $level) = @_;
+ return '' if $hr->{SKIP}; # suppress line if a callback said so
+
$text =~ s/\(\?\(([^\#]*?)\#(\w+)([^\#]*?)\)\?\)/
- $hr->{$2} ? $1.$hr->{$2}.$3 : ""/eg;
+ $hr->{$2} ? $1.$hr->{$2}.$3 : ""/eg;
+
$text =~ s/\(x\((.*?);(.*?)\)x\)/$order eq "exec" ? $1 : $2/egs;
$text =~ s/\(\*\(([^;]*?)\)\*\)/$1 x $level/egs;
$text =~ s/\(\*\((.*?);(.*?)\)\*\)/$1 x ($level - 1) . $2 x ($level>0)/egs;
- $text =~ s/#([a-zA-Z]+)(\d+)/sprintf("%-$2s", $hr->{$1})/eg;
- $text =~ s/#([a-zA-Z]+)/$hr->{$1}/eg;
+ $text =~ s/\#([a-zA-Z]+)(\d+)/sprintf("%-$2s", $hr->{$1})/eg;
+
+ $text =~ s/\#([a-zA-Z]+)/$hr->{$1}/eg; # populate data into template
$text =~ s/[ \t]*~+[ \t]*/ /g;
- return $text;
+ chomp $text;
+ return "$text\n" if $text ne "";
+ return $text; # suppress empty lines
}
my %priv;
@@ -381,7 +454,7 @@ $priv{$_}{128} = "LVINTRO"
"padav", "padhv", "enteriter");
$priv{$_}{64} = "REFC" for ("leave", "leavesub", "leavesublv", "leavewrite");
$priv{"aassign"}{64} = "COMMON";
-$priv{"aassign"}{32} = "PHASH";
+$priv{"aassign"}{32} = "PHASH" if $] < 5.009;
$priv{"sassign"}{64} = "BKWARD";
$priv{$_}{64} = "RTIME" for ("match", "subst", "substcont");
@{$priv{"trans"}}{1,2,4,8,16,64} = ("<UTF", ">UTF", "IDENT", "SQUASH", "DEL",
@@ -389,7 +462,7 @@ $priv{$_}{64} = "RTIME" for ("match", "subst", "substcont");
$priv{"repeat"}{64} = "DOLIST";
$priv{"leaveloop"}{64} = "CONT";
@{$priv{$_}}{32,64,96} = ("DREFAV", "DREFHV", "DREFSV")
- for ("entersub", map("rv2${_}v", "a", "s", "h", "g"), "aelem", "helem");
+ for (qw(rv2gv rv2sv padsv aelem helem));
$priv{"entersub"}{16} = "DBG";
$priv{"entersub"}{32} = "TARG";
@{$priv{$_}}{4,8,128} = ("INARGS","AMPER","NO()") for ("entersub", "rv2cv");
@@ -417,13 +490,25 @@ $priv{"exists"}{64} = "SUB";
$priv{$_}{64} = "LOCALE"
for ("sort", "prtf", "sprintf", "slt", "sle", "seq", "sne", "sgt", "sge",
"scmp", "lc", "uc", "lcfirst", "ucfirst");
-@{$priv{"sort"}}{1,2,4} = ("NUM", "INT", "REV");
+@{$priv{"sort"}}{1,2,4,8} = ("NUM", "INT", "REV", "INPLACE");
$priv{"threadsv"}{64} = "SVREFd";
@{$priv{$_}}{16,32,64,128} = ("INBIN","INCR","OUTBIN","OUTCR")
for ("open", "backtick");
$priv{"exit"}{128} = "VMS";
$priv{$_}{2} = "FTACCESS"
for ("ftrread", "ftrwrite", "ftrexec", "fteread", "ftewrite", "fteexec");
+if ($] >= 5.009) {
+ # Stacked filetests are post 5.8.x
+ $priv{$_}{4} = "FTSTACKED"
+ for ("ftrread", "ftrwrite", "ftrexec", "fteread", "ftewrite", "fteexec",
+ "ftis", "fteowned", "ftrowned", "ftzero", "ftsize", "ftmtime",
+ "ftatime", "ftctime", "ftsock", "ftchr", "ftblk", "ftfile", "ftdir",
+ "ftpipe", "ftlink", "ftsuid", "ftsgid", "ftsvtx", "fttty", "fttext",
+ "ftbinary");
+ # Lexical $_ is post 5.8.x
+ $priv{$_}{2} = "GREPLEX"
+ for ("mapwhile", "mapstart", "grepwhile", "grepstart");
+}
sub private_flags {
my($name, $x) = @_;
@@ -497,7 +582,17 @@ sub concise_op {
if (defined $padname and class($padname) ne "SPECIAL") {
$h{targarg} = $padname->PVX;
if ($padname->FLAGS & SVf_FAKE) {
- $h{targarglife} = "$h{targarg}:FAKE";
+ if ($] < 5.009) {
+ $h{targarglife} = "$h{targarg}:FAKE";
+ } else {
+ # These changes relate to the jumbo closure fix.
+ # See changes 19939 and 20005
+ my $fake = '';
+ $fake .= 'a' if $padname->IVX & 1; # PAD_FAKELEX_ANON
+ $fake .= 'm' if $padname->IVX & 2; # PAD_FAKELEX_MULTI
+ $fake .= ':' . $padname->NVX if $curcv->CvFLAGS & CVf_ANON;
+ $h{targarglife} = "$h{targarg}:FAKE:$fake";
+ }
}
else {
my $intro = $padname->NVX - $cop_seq_base;
@@ -559,12 +654,14 @@ sub concise_op {
undef $lastnext;
$h{arg} = "(other->" . seq($op->other) . ")";
} elsif ($h{class} eq "SVOP") {
- if (! ${$op->sv}) {
- my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
- $h{arg} = "[" . concise_sv($sv, \%h) . "]";
- $h{targarglife} = $h{targarg} = "";
- } else {
- $h{arg} = "(" . concise_sv($op->sv, \%h) . ")";
+ unless ($h{name} eq 'aelemfast' and $op->flags & OPf_SPECIAL) {
+ if (! ${$op->sv}) {
+ my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
+ $h{arg} = "[" . concise_sv($sv, \%h) . "]";
+ $h{targarglife} = $h{targarg} = "";
+ } else {
+ $h{arg} = "(" . concise_sv($op->sv, \%h) . ")";
+ }
}
} elsif ($h{class} eq "PADOP") {
my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->padix];
@@ -589,19 +686,21 @@ sub concise_op {
$h{label} = $labels{$op->seq};
$h{typenum} = $op->type;
$h{noise} = $linenoise[$op->type];
- $_->(\%h, $op, \$format, \$level) for @callbacks;
+
+ $_->(\%h, $op, \$format, \$level, $stylename) for @callbacks;
return fmt_line(\%h, $format, $level);
}
sub B::OP::concise {
my($op, $level) = @_;
if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
+ # insert a 'goto' line
my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
"addr" => sprintf("%#x", $$lastnext)};
- print fmt_line($h, $gotofmt, $level+1);
+ print $walkHandle fmt_line($h, $gotofmt, $level+1);
}
$lastnext = $op->next;
- print concise_op($op, $level, $format);
+ print $walkHandle concise_op($op, $level, $format);
}
# B::OP::terse (see Terse.pm) now just calls this
@@ -620,6 +719,7 @@ sub b_terse {
$curcv = main_cv unless $curcv;
if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
+ # insert a 'goto'
my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
"addr" => sprintf("%#x", $$lastnext)};
print fmt_line($h, $style{"terse"}[1], $level+1);
@@ -651,7 +751,7 @@ sub tree {
if (substr($lines[$i], 0, 1) eq " ") {
$lines[$i] = $nokid . $lines[$i];
} else {
- $lines[$i] = $kid . $lines[$i];
+ $lines[$i] = $kid . $lines[$i];
}
}
$lines[$i] = $kids . $lines[$i];
@@ -686,7 +786,7 @@ sub tree {
# sequence numbers which are easier to control. This way we also don't
# stand in the way of a possible future removal of OP sequence
# numbers).
-
+
# When you say "perl -MO=Concise -e '$a'", the output should look like:
# 4 <@> leave[t1] vKP/REFC ->(end)
@@ -732,8 +832,8 @@ sophisticated and flexible.
=head1 EXAMPLE
-Here's is a short example of output, using the default formatting
-conventions :
+Here's is a short example of output (aka 'rendering'), using the
+default formatting conventions :
% perl -MO=Concise -e '$a = $b + 42'
8 <@> leave[1 ref] vKP/REFC ->(end)
@@ -747,7 +847,7 @@ conventions :
- <1> ex-rv2sv sKRM*/1 ->7
6 <$> gvsv(*a) s ->7
-Each line corresponds to an operator. Null ops appear as C<ex-opname>,
+Each line corresponds to an opcode. Null ops appear as C<ex-opname>,
where I<opname> is the op that has been optimized away by perl.
The number on the first row indicates the op's sequence number. It's
@@ -777,6 +877,16 @@ including use'd or require'd files) is printed. Passing C<BEGIN>,
C<CHECK>, C<INIT>, or C<END> will cause all of the corresponding
special blocks to be printed.
+Options affect how things are rendered (ie printed). They're presented
+here by their visual effect, 1st being strongest. They're grouped
+according to how they interrelate; within each group the options are
+mutually exclusive (unless otherwise stated).
+
+=head2 Options for Opcode Ordering
+
+These options control the 'vertical display' of opcodes. The display
+'order' is also called 'mode' elsewhere in this document.
+
=over 4
=item B<-basic>
@@ -803,6 +913,50 @@ at the left and 'left-to-right' order of children transformed into
it isn't suitable for large programs (unless you have a very wide
terminal).
+=back
+
+=head2 Options for Line-Style
+
+These options select the line-style (or just style) used to render
+each opcode, and dictates what info is actually printed into each line.
+
+=over 4
+
+=item B<-concise>
+
+Use the author's favorite set of formatting conventions. This is the
+default, of course.
+
+=item B<-terse>
+
+Use formatting conventions that emulate the output of B<B::Terse>. The
+basic mode is almost indistinguishable from the real B<B::Terse>, and the
+exec mode looks very similar, but is in a more logical order and lacks
+curly brackets. B<B::Terse> doesn't have a tree mode, so the tree mode
+is only vaguely reminiscent of B<B::Terse>.
+
+=item B<-linenoise>
+
+Use formatting conventions in which the name of each OP, rather than being
+written out in full, is represented by a one- or two-character abbreviation.
+This is mainly a joke.
+
+=item B<-debug>
+
+Use formatting conventions reminiscent of B<B::Debug>; these aren't
+very concise at all.
+
+=item B<-env>
+
+Use formatting conventions read from the environment variables
+C<B_CONCISE_FORMAT>, C<B_CONCISE_GOTO_FORMAT>, and C<B_CONCISE_TREE_FORMAT>.
+
+=back
+
+=head2 Options for tree-specific formatting
+
+=over 4
+
=item B<-compact>
Use a tree format in which the minimum amount of space is used for the
@@ -827,10 +981,13 @@ look as clean as the VT100 characters, but they'll work with almost any
terminal (or the horizontal scrolling mode of less(1)) and are suitable
for text documentation or email. This is the default.
-=item B<-main>
+=back
-Include the main program in the output, even if subroutines were also
-specified.
+These are pairwise exclusive, i.e. compact or loose, vt or ascii.
+
+=head2 Options controlling sequence numbering
+
+=over 4
=item B<-base>I<n>
@@ -846,47 +1003,51 @@ usual convention for Arabic numerals, and the default.
=item B<-littleendian>
-Print seqence numbers with the least significant digit first.
+Print seqence numbers with the least significant digit first. This is
+obviously mutually exclusive with bigendian.
-=item B<-concise>
-
-Use the author's favorite set of formatting conventions. This is the
-default, of course.
+=back
-=item B<-terse>
+=head2 Other options
-Use formatting conventions that emulate the output of B<B::Terse>. The
-basic mode is almost indistinguishable from the real B<B::Terse>, and the
-exec mode looks very similar, but is in a more logical order and lacks
-curly brackets. B<B::Terse> doesn't have a tree mode, so the tree mode
-is only vaguely reminiscient of B<B::Terse>.
+=over 4
-=item B<-linenoise>
+=item B<-main>
-Use formatting conventions in which the name of each OP, rather than being
-written out in full, is represented by a one- or two-character abbreviation.
-This is mainly a joke.
+Include the main program in the output, even if subroutines were also
+specified. This is the only option that is not sticky (see below)
-=item B<-debug>
+=item B<-banner>
-Use formatting conventions reminiscient of B<B::Debug>; these aren't
-very concise at all.
+B::Concise::compile normally prints a banner line identifying the
+function name, or in case of a subref, a generic message including
+(unfortunately) the stringified coderef. This option suppresses the
+printing of the banner.
-=item B<-env>
+=back
-Use formatting conventions read from the environment variables
-C<B_CONCISE_FORMAT>, C<B_CONCISE_GOTO_FORMAT>, and C<B_CONCISE_TREE_FORMAT>.
+=head2 Option Stickiness
-=back
+If you invoke Concise more than once in a program, you should know that
+the options are 'sticky'. This means that the options you provide in
+the first call will be remembered for the 2nd call, unless you
+re-specify or change them.
=head1 FORMATTING SPECIFICATIONS
-For each general style ('concise', 'terse', 'linenoise', etc.) there are
-three specifications: one of how OPs should appear in the basic or exec
-modes, one of how 'goto' lines should appear (these occur in the exec
-mode only), and one of how nodes should appear in tree mode. Each has the
-same format, described below. Any text that doesn't match a special
-pattern is copied verbatim.
+For each line-style ('concise', 'terse', 'linenoise', etc.) there are
+3 format-specs which control how OPs are rendered.
+
+The first is the 'default' format, which is used in both basic and exec
+modes to print all opcodes. The 2nd, goto-format, is used in exec
+mode when branches are encountered. They're not real opcodes, and are
+inserted to look like a closing curly brace. The tree-format is tree
+specific.
+
+When a line is rendered, the correct format string is scanned for the
+following items, and data is substituted in, or other manipulations,
+like basic indenting. Any text that doesn't match a special pattern
+(the items below) is copied verbatim. (Yes, it's a set of s///g steps.)
=over 4
@@ -1092,43 +1253,117 @@ The numeric value of the OP's type, in decimal.
=head1 Using B::Concise outside of the O framework
-It is possible to extend B<B::Concise> by using it outside of the B<O>
-framework and providing new styles and new variables.
+You can use B<B::Concise>, and call compile() directly, and
+repeatedly. By doing so, you can avoid the compile-time only
+operation of 'perl -MO=Concise ..'. For example, you can use the
+debugger to step through B::Concise::compile() itself.
+
+When doing so, you can alter Concise output by providing new output
+styles, and optionally by adding callback routines which populate new
+variables that may be rendered as part of those styles. For all
+following sections, please review L</FORMATTING SPECIFICATIONS>.
+
+=head2 Example: Altering Concise Renderings
use B::Concise qw(set_style add_callback);
- set_style($format, $gotofmt, $treefmt);
+ set_style($your_format, $your_gotofmt, $your_treefmt);
add_callback
- (
- sub
- {
- my ($h, $op, $level, $format) = @_;
+ ( sub {
+ my ($h, $op, $format, $level, $stylename) = @_;
$h->{variable} = some_func($op);
}
- );
+ );
B::Concise::compile(@options)->();
-You can specify a style by calling the B<set_style> subroutine. If you
-have a new variable in your style, or you want to change the value of an
-existing variable, you will need to add a callback to specify the value
-for that variable.
+=head2 set_style()
+
+B<set_style> accepts 3 arguments, and updates the three format-specs
+comprising a line-style (basic-exec, goto, tree). It has one minor
+drawback though; it doesn't register the style under a new name. This
+can become an issue if you render more than once and switch styles.
+Thus you may prefer to use add_style() and/or set_style_standard()
+instead.
+
+=head2 set_style_standard($name)
+
+This restores one of the standard line-styles: C<terse>, C<concise>,
+C<linenoise>, C<debug>, C<env>, into effect. It also accepts style
+names previously defined with add_style().
-This is done by calling B<add_callback> passing references to any
-callback subroutines. The subroutines are called in the same order as
-they are added. Each subroutine is passed four parameters. These are a
-reference to a hash, the keys of which are the names of the variables
-and the values of which are their values, the op, the level and the
-format.
+=head2 add_style()
+
+This subroutine accepts a new style name and three style arguments as
+above, and creates, registers, and selects the newly named style. It is
+an error to re-add a style; call set_style_standard() to switch between
+several styles.
+
+=head2 add_callback()
+
+If your newly minted styles refer to any #variables, you'll need to
+define a callback subroutine that will populate (or modify) those
+variables. They are then available for use in the style you've chosen.
+
+The callbacks are called for each opcode visited by Concise, in the
+same order as they are added. Each subroutine is passed five
+parameters.
+
+ 1. A hashref, containing the variable names and values which are
+ populated into the report-line for the op
+ 2. the op, as a B<B::OP> object
+ 3. a reference to the format string
+ 4. the formatting (indent) level
+ 5. the selected stylename
To define your own variables, simply add them to the hash, or change
existing values if you need to. The level and format are passed in as
references to scalars, but it is unlikely that they will need to be
changed or even used.
+=head2 Running B::Concise::compile()
+
+B<compile> accepts options as described above in L</OPTIONS>, and
+arguments, which are either coderefs, or subroutine names.
+
+compile() constructs and returns a coderef, which when invoked, scans
+the optree, and prints the results to STDOUT. Once you have the
+coderef, you may change the output style; thereafter the coderef renders
+in the new style.
+
+B<walk_output> lets you change the print destination from STDOUT to
+another open filehandle, or into a string passed as a ref.
+
+ walk_output(\my $buf);
+ my $walker = B::Concise::compile('-concise','funcName', \&aSubRef);
+ print "Concise Banner for Functions: $buf\n";
+ $walker->();
+ print "Concise Rendering(s)?: $buf\n";
+
+For each subroutine visited by Concise, the $buf will contain a
+banner naming the function or coderef about to be traversed.
+Once $walker is invoked, it prints the actual renderings for each.
+
To switch back to one of the standard styles like C<concise> or
-C<terse>, use C<set_style_standard>.
+C<terse>, call C<set_style_standard>, or pass the style name into
+B::Concise::compile() (as done above).
+
+=head2 B::Concise::reset_sequence()
+
+This function (not exported) lets you reset the sequence numbers (note
+that they're numbered arbitrarily, their goal being to be human
+readable). Its purpose is mostly to support testing, i.e. to compare
+the concise output from two identical anonymous subroutines (but
+different instances). Without the reset, B::Concise, seeing that
+they're separate optrees, generates different sequence numbers in
+the output.
+
+=head2 Errors
+
+All detected errors, (invalid arguments, internal errors, etc.) are
+resolved with a die($message). Use an eval if you wish to catch these
+errors and continue processing.
-To see the output, call the subroutine returned by B<compile> in the
-same way that B<O> does.
+In particular, B<compile> will die if you've asked for a non-existent
+function-name, a non-existent coderef, or a non-CODE reference.
=head1 AUTHOR