📄 b.pm
字号:
# B.pm## Copyright (c) 1996, 1997, 1998 Malcolm Beattie## You may distribute under the terms of either the GNU General Public# License or the Artistic License, as specified in the README file.#package B;our $VERSION = '1.17';use XSLoader ();require Exporter;@ISA = qw(Exporter);# walkoptree_slow comes from B.pm (you are there),# walkoptree comes from B.xs@EXPORT_OK = qw(minus_c ppname save_BEGINs class peekop cast_I32 cstring cchar hash threadsv_names main_root main_start main_cv svref_2object opnumber sub_generation amagic_generation perlstring walkoptree_slow walkoptree walkoptree_exec walksymtable parents comppadlist sv_undef compile_stats timing_info begin_av init_av check_av end_av regex_padav dowarn defstash curstash warnhook diehook inc_gv @optype @specialsv_name );push @EXPORT_OK, qw(unitcheck_av) if $] > 5.009;sub OPf_KIDS ();use strict;@B::SV::ISA = 'B::OBJECT';@B::NULL::ISA = 'B::SV';@B::PV::ISA = 'B::SV';@B::IV::ISA = 'B::SV';@B::NV::ISA = 'B::SV';@B::RV::ISA = 'B::SV';@B::PVIV::ISA = qw(B::PV B::IV);@B::PVNV::ISA = qw(B::PVIV B::NV);@B::PVMG::ISA = 'B::PVNV';# Change in the inheritance hierarchy post 5.9.0@B::PVLV::ISA = $] > 5.009 ? 'B::GV' : 'B::PVMG';# BM is eliminated post 5.9.5, but effectively is a specialisation of GV now.@B::BM::ISA = $] > 5.009005 ? 'B::GV' : 'B::PVMG';@B::AV::ISA = 'B::PVMG';@B::GV::ISA = 'B::PVMG';@B::HV::ISA = 'B::PVMG';@B::CV::ISA = 'B::PVMG';@B::IO::ISA = 'B::PVMG';@B::FM::ISA = 'B::CV';@B::OP::ISA = 'B::OBJECT';@B::UNOP::ISA = 'B::OP';@B::BINOP::ISA = 'B::UNOP';@B::LOGOP::ISA = 'B::UNOP';@B::LISTOP::ISA = 'B::BINOP';@B::SVOP::ISA = 'B::OP';@B::PADOP::ISA = 'B::OP';@B::PVOP::ISA = 'B::OP';@B::LOOP::ISA = 'B::LISTOP';@B::PMOP::ISA = 'B::LISTOP';@B::COP::ISA = 'B::OP';@B::SPECIAL::ISA = 'B::OBJECT';@B::optype = qw(OP UNOP BINOP LOGOP LISTOP PMOP SVOP PADOP PVOP LOOP COP);# bytecode.pl contained the following comment:# Nullsv *must* come first in the following so that the condition# ($$sv == 0) can continue to be used to test (sv == Nullsv).@B::specialsv_name = qw(Nullsv &PL_sv_undef &PL_sv_yes &PL_sv_no (SV*)pWARN_ALL (SV*)pWARN_NONE (SV*)pWARN_STD);{ # Stop "-w" from complaining about the lack of a real B::OBJECT class package B::OBJECT;}sub B::GV::SAFENAME { my $name = (shift())->NAME; # The regex below corresponds to the isCONTROLVAR macro # from toke.c $name =~ s/^([\cA-\cZ\c\\c[\c]\c?\c_\c^])/"^". chr( utf8::unicode_to_native( 64 ^ ord($1) ))/e; # When we say unicode_to_native we really mean ascii_to_native, # which matters iff this is a non-ASCII platform (EBCDIC). return $name;}sub B::IV::int_value { my ($self) = @_; return (($self->FLAGS() & SVf_IVisUV()) ? $self->UVX : $self->IV);}sub B::NULL::as_string() {""}sub B::IV::as_string() {goto &B::IV::int_value}sub B::PV::as_string() {goto &B::PV::PV}my $debug;my $op_count = 0;my @parents = ();sub debug { my ($class, $value) = @_; $debug = $value; walkoptree_debug($value);}sub class { my $obj = shift; my $name = ref $obj; $name =~ s/^.*:://; return $name;}sub parents { \@parents }# For debuggingsub peekop { my $op = shift; return sprintf("%s (0x%x) %s", class($op), $$op, $op->name);}sub walkoptree_slow { my($op, $method, $level) = @_; $op_count++; # just for statistics $level ||= 0; warn(sprintf("walkoptree: %d. %s\n", $level, peekop($op))) if $debug; $op->$method($level) if $op->can($method); if ($$op && ($op->flags & OPf_KIDS)) { my $kid; unshift(@parents, $op); for ($kid = $op->first; $$kid; $kid = $kid->sibling) { walkoptree_slow($kid, $method, $level + 1); } shift @parents; } if (class($op) eq 'PMOP' && ref($op->pmreplroot) && ${$op->pmreplroot} && $op->pmreplroot->isa( 'B::OP' )) { unshift(@parents, $op); walkoptree_slow($op->pmreplroot, $method, $level + 1); shift @parents; }}sub compile_stats { return "Total number of OPs processed: $op_count\n";}sub timing_info { my ($sec, $min, $hr) = localtime; my ($user, $sys) = times; sprintf("%02d:%02d:%02d user=$user sys=$sys", $hr, $min, $sec, $user, $sys);}my %symtable;sub clearsym { %symtable = ();}sub savesym { my ($obj, $value) = @_;# warn(sprintf("savesym: sym_%x => %s\n", $$obj, $value)); # debug $symtable{sprintf("sym_%x", $$obj)} = $value;}sub objsym { my $obj = shift; return $symtable{sprintf("sym_%x", $$obj)};}sub walkoptree_exec { my ($op, $method, $level) = @_; $level ||= 0; my ($sym, $ppname); my $prefix = " " x $level; for (; $$op; $op = $op->next) { $sym = objsym($op); if (defined($sym)) { print $prefix, "goto $sym\n"; return; } savesym($op, sprintf("%s (0x%lx)", class($op), $$op)); $op->$method($level); $ppname = $op->name; if ($ppname =~ /^(d?or(assign)?|and(assign)?|mapwhile|grepwhile|entertry|range|cond_expr)$/) { print $prefix, uc($1), " => {\n"; walkoptree_exec($op->other, $method, $level + 1); print $prefix, "}\n"; } elsif ($ppname eq "match" || $ppname eq "subst") { my $pmreplstart = $op->pmreplstart; if ($$pmreplstart) { print $prefix, "PMREPLSTART => {\n"; walkoptree_exec($pmreplstart, $method, $level + 1); print $prefix, "}\n"; } } elsif ($ppname eq "substcont") { print $prefix, "SUBSTCONT => {\n"; walkoptree_exec($op->other->pmreplstart, $method, $level + 1); print $prefix, "}\n"; $op = $op->other; } elsif ($ppname eq "enterloop") { print $prefix, "REDO => {\n"; walkoptree_exec($op->redoop, $method, $level + 1); print $prefix, "}\n", $prefix, "NEXT => {\n"; walkoptree_exec($op->nextop, $method, $level + 1); print $prefix, "}\n", $prefix, "LAST => {\n"; walkoptree_exec($op->lastop, $method, $level + 1); print $prefix, "}\n"; } elsif ($ppname eq "subst") { my $replstart = $op->pmreplstart; if ($$replstart) { print $prefix, "SUBST => {\n"; walkoptree_exec($replstart, $method, $level + 1); print $prefix, "}\n"; } } }}sub walksymtable { my ($symref, $method, $recurse, $prefix) = @_; my $sym; my $ref; my $fullname; no strict 'refs'; $prefix = '' unless defined $prefix; while (($sym, $ref) = each %$symref) { $fullname = "*main::".$prefix.$sym; if ($sym =~ /::$/) { $sym = $prefix . $sym; if ($sym ne "main::" && $sym ne "<none>::" && &$recurse($sym)) { walksymtable(\%$fullname, $method, $recurse, $sym); } } else { svref_2object(\*$fullname)->$method(); } }}{ package B::Section; my $output_fh; my %sections; sub new { my ($class, $section, $symtable, $default) = @_; $output_fh ||= FileHandle->new_tmpfile; my $obj = bless [-1, $section, $symtable, $default], $class; $sections{$section} = $obj; return $obj; } sub get { my ($class, $section) = @_; return $sections{$section}; } sub add { my $section = shift; while (defined($_ = shift)) { print $output_fh "$section->[1]\t$_\n"; $section->[0]++; } } sub index { my $section = shift; return $section->[0]; } sub name { my $section = shift; return $section->[1]; } sub symtable { my $section = shift; return $section->[2]; } sub default { my $section = shift; return $section->[3]; } sub output { my ($section, $fh, $format) = @_; my $name = $section->name; my $sym = $section->symtable || {}; my $default = $section->default; seek($output_fh, 0, 0); while (<$output_fh>) { chomp; s/^(.*?)\t//; if ($1 eq $name) { s{(s\\_[0-9a-f]+)} { exists($sym->{$1}) ? $sym->{$1} : $default; }ge; printf $fh $format, $_; } } }}XSLoader::load 'B';1;__END__=head1 NAMEB - The Perl Compiler=head1 SYNOPSIS use B;=head1 DESCRIPTIONThe C<B> module supplies classes which allow a Perl program to delveinto its own innards. It is the module used to implement the"backends" of the Perl compiler. Usage of the compiler does notrequire knowledge of this module: see the F<O> module for theuser-visible part. The C<B> module is of use to those who want towrite new compiler backends. This documentation assumes that thereader knows a fair amount about perl's internals including suchthings as SVs, OPs and the internal symbol table and syntax treeof a program.=head1 OVERVIEWThe C<B> module contains a set of utility functions for querying thecurrent state of the Perl interpreter; typically these functionsreturn objects from the B::SV and B::OP classes, or their derivedclasses. These classes in turn define methods for querying theresulting objects about their own internal state.=head1 Utility FunctionsThe C<B> module exports a variety of functions: some are simpleutility functions, others provide a Perl program with a way toget an initial "handle" on an internal object.=head2 Functions Returning C<B::SV>, C<B::AV>, C<B::HV>, and C<B::CV> objectsFor descriptions of the class hierarchy of these objects and themethods that can be called on them, see below, L<"OVERVIEW OFCLASSES"> and L<"SV-RELATED CLASSES">.=over 4=item sv_undefReturns the SV object corresponding to the C variable C<sv_undef>.=item sv_yesReturns the SV object corresponding to the C variable C<sv_yes>.=item sv_noReturns the SV object corresponding to the C variable C<sv_no>.=item svref_2object(SVREF)Takes a reference to any Perl value, and turns the referred-to valueinto an object in the appropriate B::OP-derived or B::SV-derivedclass. Apart from functions such as C<main_root>, this is the primaryway to get an initial "handle" on an internal perl data structurewhich can then be followed with the other access methods.The returned object will only be valid as long as the underlying OPsand SVs continue to exist. Do not attempt to use the object after theunderlying structures are freed.=item amagic_generationReturns the SV object corresponding to the C variable C<amagic_generation>.=item init_avReturns the AV object (i.e. in class B::AV) representing INIT blocks.=item check_avReturns the AV object (i.e. in class B::AV) representing CHECK blocks.=item unitcheck_avReturns the AV object (i.e. in class B::AV) representing UNITCHECK blocks.=item begin_avReturns the AV object (i.e. in class B::AV) representing BEGIN blocks.=item end_avReturns the AV object (i.e. in class B::AV) representing END blocks.=item comppadlistReturns the AV object (i.e. in class B::AV) of the global comppadlist.=item regex_padavOnly when perl was compiled with ithreads.=item main_cvReturn the (faked) CV corresponding to the main part of the Perlprogram.=back=head2 Functions for Examining the Symbol Table=over 4=item walksymtable(SYMREF, METHOD, RECURSE, PREFIX)Walk the symbol table starting at SYMREF and call METHOD on eachsymbol (a B::GV object) visited. When the walk reaches packagesymbols (such as "Foo::") it invokes RECURSE, passing in the symbolname, and only recurses into the package if that sub returns true.PREFIX is the name of the SYMREF you're walking.For example: # Walk CGI's symbol table calling print_subs on each symbol. # Recurse only into CGI::Util:: walksymtable(\%CGI::, 'print_subs', sub { $_[0] eq 'CGI::Util::' }, 'CGI::');print_subs() is a B::GV method you have declared. Also see L<"B::GVMethods">, below.=back=head2 Functions Returning C<B::OP> objects or for walking op treesFor descriptions of the class hierarchy of these objects and themethods that can be called on them, see below, L<"OVERVIEW OFCLASSES"> and L<"OP-RELATED CLASSES">.=over 4=item main_rootReturns the root op (i.e. an object in the appropriate B::OP-derivedclass) of the main part of the Perl program.=item main_startReturns the starting op of the main part of the Perl program.=item walkoptree(OP, METHOD)Does a tree-walk of the syntax tree based at OP and calls METHOD oneach op it visits. Each node is visited before its children. IfC<walkoptree_debug> (see below) has been called to turn debugging on thenthe method C<walkoptree_debug> is called on each op before METHOD iscalled.=item walkoptree_debug(DEBUG)Returns the current debugging flag for C<walkoptree>. If the optionalDEBUG argument is non-zero, it sets the debugging flag to that. Seethe description of C<walkoptree> above for what the debugging flagdoes.=back=head2 Miscellaneous Utility Functions=over 4=item ppname(OPNUM)Return the PP function name (e.g. "pp_add") of op number OPNUM.=item hash(STR)Returns a string in the form "0x..." representing the value of theinternal hash function used by perl on string STR.=item cast_I32(I)Casts I to the internal I32 type used by that perl.=item minus_cDoes the equivalent of the C<-c> command-line option. Obviously, thisis only useful in a BEGIN block or else the flag is set too late.=item cstring(STR)Returns a double-quote-surrounded escaped version of STR which canbe used as a string in C source code.=item perlstring(STR)Returns a double-quote-surrounded escaped version of STR which canbe used as a string in Perl source code.=item class(OBJ)Returns the class of an object without the part of the classnamepreceding the first C<"::">. This is used to turn C<"B::UNOP"> intoC<"UNOP"> for example.=item threadsv_namesIn a perl compiled for threads, this returns a list of the specialper-thread threadsv variables.=back=head2 Exported utility variabiles=over 4=item @optype my $op_type = $optype[$op_type_num];A simple mapping of the op type number to its type (like 'COP' or 'BINOP').=item @specialsv_name my $sv_name = $specialsv_name[$sv_index];Certain SV types are considered 'special'. They're represented byB::SPECIAL and are referred to by a number from the specialsv_list.This array maps that number back to the name of the SV (like 'Nullsv'or '&PL_sv_undef').=back=head1 OVERVIEW OF CLASSESThe C structures used by Perl's internals to hold SV and OPinformation (PVIV, AV, HV, ..., OP, SVOP, UNOP, ...) are modelled on aclass hierarchy and the C<B> module gives access to them via a trueobject hierarchy. Structure fields which point to other objects(whether types of SV or types of OP) are represented by the C<B>module as Perl objects of the appropriate class.The bulk of the C<B> module is the methods for accessing fields ofthese structures.Note that all access is read-only. You cannot modify the internals byusing this module. Also, note that the B::OP and B::SV objects createdby this module are only valid for as long as the underlying objectsexist; their creation doesn't increase the reference counts of theunderlying objects. Trying to access the fields of a freed object willgive incomprehensible results, or worse.=head2 SV-RELATED CLASSESB::IV, B::NV, B::RV, B::PV, B::PVIV, B::PVNV, B::PVMG, B::BM (5.9.5 andearlier), B::PVLV, B::AV, B::HV, B::CV, B::GV, B::FM, B::IO. These classescorrespond in the obvious way to the underlying C structures of similar names.The inheritance hierarchy mimics the underlying C "inheritance". For 5.9.5and later this is: B::SV
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -