summaryrefslogtreecommitdiffstats
path: root/contrib/perl5/ext/B
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/perl5/ext/B')
-rw-r--r--contrib/perl5/ext/B/B.pm892
-rw-r--r--contrib/perl5/ext/B/B.xs1285
-rw-r--r--contrib/perl5/ext/B/B/Asmdata.pm172
-rw-r--r--contrib/perl5/ext/B/B/Assembler.pm285
-rw-r--r--contrib/perl5/ext/B/B/Bblock.pm180
-rw-r--r--contrib/perl5/ext/B/B/Bytecode.pm998
-rw-r--r--contrib/perl5/ext/B/B/C.pm1657
-rw-r--r--contrib/perl5/ext/B/B/CC.pm2002
-rw-r--r--contrib/perl5/ext/B/B/Concise.pm823
-rw-r--r--contrib/perl5/ext/B/B/Debug.pm283
-rw-r--r--contrib/perl5/ext/B/B/Deparse.pm3128
-rw-r--r--contrib/perl5/ext/B/B/Disassembler.pm185
-rw-r--r--contrib/perl5/ext/B/B/Lint.pm362
-rw-r--r--contrib/perl5/ext/B/B/Showlex.pm97
-rw-r--r--contrib/perl5/ext/B/B/Stackobj.pm346
-rw-r--r--contrib/perl5/ext/B/B/Stash.pm50
-rw-r--r--contrib/perl5/ext/B/B/Terse.pm153
-rw-r--r--contrib/perl5/ext/B/B/Xref.pm420
-rwxr-xr-xcontrib/perl5/ext/B/B/assemble30
-rw-r--r--contrib/perl5/ext/B/B/cc_harness12
-rwxr-xr-xcontrib/perl5/ext/B/B/disassemble22
-rw-r--r--contrib/perl5/ext/B/B/makeliblinks54
-rw-r--r--contrib/perl5/ext/B/Makefile.PL48
-rw-r--r--contrib/perl5/ext/B/NOTES168
-rw-r--r--contrib/perl5/ext/B/O.pm86
-rw-r--r--contrib/perl5/ext/B/README325
-rw-r--r--contrib/perl5/ext/B/TESTS78
-rw-r--r--contrib/perl5/ext/B/Todo37
-rw-r--r--contrib/perl5/ext/B/defsubs_h.PL42
-rw-r--r--contrib/perl5/ext/B/ramblings/cc.notes32
-rw-r--r--contrib/perl5/ext/B/ramblings/curcop.runtime39
-rw-r--r--contrib/perl5/ext/B/ramblings/flip-flop54
-rw-r--r--contrib/perl5/ext/B/ramblings/magic93
-rw-r--r--contrib/perl5/ext/B/ramblings/reg.alloc32
-rw-r--r--contrib/perl5/ext/B/ramblings/runtime.porting357
-rw-r--r--contrib/perl5/ext/B/typemap69
36 files changed, 0 insertions, 14896 deletions
diff --git a/contrib/perl5/ext/B/B.pm b/contrib/perl5/ext/B/B.pm
deleted file mode 100644
index c58e769..0000000
--- a/contrib/perl5/ext/B/B.pm
+++ /dev/null
@@ -1,892 +0,0 @@
-# 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;
-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
- amagic_generation
- walkoptree_slow walkoptree walkoptree_exec walksymtable
- parents comppadlist sv_undef compile_stats timing_info
- begin_av init_av end_av);
-
-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::IV';
-@B::RV::ISA = 'B::SV';
-@B::PVIV::ISA = qw(B::PV B::IV);
-@B::PVNV::ISA = qw(B::PV B::NV);
-@B::PVMG::ISA = 'B::PVNV';
-@B::PVLV::ISA = 'B::PVMG';
-@B::BM::ISA = '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::CVOP::ISA = 'B::OP';
-@B::LOOP::ISA = 'B::LISTOP';
-@B::PMOP::ISA = 'B::LISTOP';
-@B::COP::ISA = 'B::OP';
-
-@B::SPECIAL::ISA = 'B::OBJECT';
-
-{
- # 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(64 ^ ord($1))/e;
- return $name;
-}
-
-sub B::IV::int_value {
- my ($self) = @_;
- return (($self->FLAGS() & SVf_IVisUV()) ? $self->UVX : $self->IV);
-}
-
-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 debugging
-sub 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 && ($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;
- }
-}
-
-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 =~
- /^(or|and|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;
- no strict 'vars';
- local(*glob);
- $prefix = '' unless defined $prefix;
- while (($sym, $ref) = each %$symref) {
- *glob = "*main::".$prefix.$sym;
- if ($sym =~ /::$/) {
- $sym = $prefix . $sym;
- if ($sym ne "main::" && $sym ne "<none>::" && &$recurse($sym)) {
- walksymtable(\%glob, $method, $recurse, $sym);
- }
- } else {
- svref_2object(\*glob)->EGV->$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 NAME
-
-B - The Perl Compiler
-
-=head1 SYNOPSIS
-
- use B;
-
-=head1 DESCRIPTION
-
-The C<B> module supplies classes which allow a Perl program to delve
-into its own innards. It is the module used to implement the
-"backends" of the Perl compiler. Usage of the compiler does not
-require knowledge of this module: see the F<O> module for the
-user-visible part. The C<B> module is of use to those who want to
-write new compiler backends. This documentation assumes that the
-reader knows a fair amount about perl's internals including such
-things as SVs, OPs and the internal symbol table and syntax tree
-of a program.
-
-=head1 OVERVIEW OF CLASSES
-
-The C structures used by Perl's internals to hold SV and OP
-information (PVIV, AV, HV, ..., OP, SVOP, UNOP, ...) are modelled on a
-class hierarchy and the C<B> module gives access to them via a true
-object 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 of these structures. Note
-that all access is read-only: you cannot modify the internals by
-using this module.
-
-=head2 SV-RELATED CLASSES
-
-B::IV, B::NV, B::RV, B::PV, B::PVIV, B::PVNV, B::PVMG, B::BM, B::PVLV,
-B::AV, B::HV, B::CV, B::GV, B::FM, B::IO. These classes correspond in
-the obvious way to the underlying C structures of similar names. The
-inheritance hierarchy mimics the underlying C "inheritance". Access
-methods correspond to the underlying C macros for field access,
-usually with the leading "class indication" prefix removed (Sv, Av,
-Hv, ...). The leading prefix is only left in cases where its removal
-would cause a clash in method name. For example, C<GvREFCNT> stays
-as-is since its abbreviation would clash with the "superclass" method
-C<REFCNT> (corresponding to the C function C<SvREFCNT>).
-
-=head2 B::SV METHODS
-
-=over 4
-
-=item REFCNT
-
-=item FLAGS
-
-=back
-
-=head2 B::IV METHODS
-
-=over 4
-
-=item IV
-
-Returns the value of the IV, I<interpreted as
-a signed integer>. This will be misleading
-if C<FLAGS & SVf_IVisUV>. Perhaps you want the
-C<int_value> method instead?
-
-=item IVX
-
-=item UVX
-
-=item int_value
-
-This method returns the value of the IV as an integer.
-It differs from C<IV> in that it returns the correct
-value regardless of whether it's stored signed or
-unsigned.
-
-=item needs64bits
-
-=item packiv
-
-=back
-
-=head2 B::NV METHODS
-
-=over 4
-
-=item NV
-
-=item NVX
-
-=back
-
-=head2 B::RV METHODS
-
-=over 4
-
-=item RV
-
-=back
-
-=head2 B::PV METHODS
-
-=over 4
-
-=item PV
-
-This method is the one you usually want. It constructs a
-string using the length and offset information in the struct:
-for ordinary scalars it will return the string that you'd see
-from Perl, even if it contains null characters.
-
-=item PVX
-
-This method is less often useful. It assumes that the string
-stored in the struct is null-terminated, and disregards the
-length information.
-
-It is the appropriate method to use if you need to get the name
-of a lexical variable from a padname array. Lexical variable names
-are always stored with a null terminator, and the length field
-(SvCUR) is overloaded for other purposes and can't be relied on here.
-
-=back
-
-=head2 B::PVMG METHODS
-
-=over 4
-
-=item MAGIC
-
-=item SvSTASH
-
-=back
-
-=head2 B::MAGIC METHODS
-
-=over 4
-
-=item MOREMAGIC
-
-=item PRIVATE
-
-=item TYPE
-
-=item FLAGS
-
-=item OBJ
-
-=item PTR
-
-=back
-
-=head2 B::PVLV METHODS
-
-=over 4
-
-=item TARGOFF
-
-=item TARGLEN
-
-=item TYPE
-
-=item TARG
-
-=back
-
-=head2 B::BM METHODS
-
-=over 4
-
-=item USEFUL
-
-=item PREVIOUS
-
-=item RARE
-
-=item TABLE
-
-=back
-
-=head2 B::GV METHODS
-
-=over 4
-
-=item is_empty
-
-This method returns TRUE if the GP field of the GV is NULL.
-
-=item NAME
-
-=item SAFENAME
-
-This method returns the name of the glob, but if the first
-character of the name is a control character, then it converts
-it to ^X first, so that *^G would return "^G" rather than "\cG".
-
-It's useful if you want to print out the name of a variable.
-If you restrict yourself to globs which exist at compile-time
-then the result ought to be unambiguous, because code like
-C<${"^G"} = 1> is compiled as two ops - a constant string and
-a dereference (rv2gv) - so that the glob is created at runtime.
-
-If you're working with globs at runtime, and need to disambiguate
-*^G from *{"^G"}, then you should use the raw NAME method.
-
-=item STASH
-
-=item SV
-
-=item IO
-
-=item FORM
-
-=item AV
-
-=item HV
-
-=item EGV
-
-=item CV
-
-=item CVGEN
-
-=item LINE
-
-=item FILE
-
-=item FILEGV
-
-=item GvREFCNT
-
-=item FLAGS
-
-=back
-
-=head2 B::IO METHODS
-
-=over 4
-
-=item LINES
-
-=item PAGE
-
-=item PAGE_LEN
-
-=item LINES_LEFT
-
-=item TOP_NAME
-
-=item TOP_GV
-
-=item FMT_NAME
-
-=item FMT_GV
-
-=item BOTTOM_NAME
-
-=item BOTTOM_GV
-
-=item SUBPROCESS
-
-=item IoTYPE
-
-=item IoFLAGS
-
-=back
-
-=head2 B::AV METHODS
-
-=over 4
-
-=item FILL
-
-=item MAX
-
-=item OFF
-
-=item ARRAY
-
-=item AvFLAGS
-
-=back
-
-=head2 B::CV METHODS
-
-=over 4
-
-=item STASH
-
-=item START
-
-=item ROOT
-
-=item GV
-
-=item FILE
-
-=item DEPTH
-
-=item PADLIST
-
-=item OUTSIDE
-
-=item XSUB
-
-=item XSUBANY
-
-=item CvFLAGS
-
-=back
-
-=head2 B::HV METHODS
-
-=over 4
-
-=item FILL
-
-=item MAX
-
-=item KEYS
-
-=item RITER
-
-=item NAME
-
-=item PMROOT
-
-=item ARRAY
-
-=back
-
-=head2 OP-RELATED CLASSES
-
-B::OP, B::UNOP, B::BINOP, B::LOGOP, B::LISTOP, B::PMOP,
-B::SVOP, B::PADOP, B::PVOP, B::CVOP, B::LOOP, B::COP.
-These classes correspond in
-the obvious way to the underlying C structures of similar names. The
-inheritance hierarchy mimics the underlying C "inheritance". Access
-methods correspond to the underlying C structre field names, with the
-leading "class indication" prefix removed (op_).
-
-=head2 B::OP METHODS
-
-=over 4
-
-=item next
-
-=item sibling
-
-=item name
-
-This returns the op name as a string (e.g. "add", "rv2av").
-
-=item ppaddr
-
-This returns the function name as a string (e.g. "PL_ppaddr[OP_ADD]",
-"PL_ppaddr[OP_RV2AV]").
-
-=item desc
-
-This returns the op description from the global C PL_op_desc array
-(e.g. "addition" "array deref").
-
-=item targ
-
-=item type
-
-=item seq
-
-=item flags
-
-=item private
-
-=back
-
-=head2 B::UNOP METHOD
-
-=over 4
-
-=item first
-
-=back
-
-=head2 B::BINOP METHOD
-
-=over 4
-
-=item last
-
-=back
-
-=head2 B::LOGOP METHOD
-
-=over 4
-
-=item other
-
-=back
-
-=head2 B::LISTOP METHOD
-
-=over 4
-
-=item children
-
-=back
-
-=head2 B::PMOP METHODS
-
-=over 4
-
-=item pmreplroot
-
-=item pmreplstart
-
-=item pmnext
-
-=item pmregexp
-
-=item pmflags
-
-=item pmpermflags
-
-=item precomp
-
-=back
-
-=head2 B::SVOP METHOD
-
-=over 4
-
-=item sv
-
-=item gv
-
-=back
-
-=head2 B::PADOP METHOD
-
-=over 4
-
-=item padix
-
-=back
-
-=head2 B::PVOP METHOD
-
-=over 4
-
-=item pv
-
-=back
-
-=head2 B::LOOP METHODS
-
-=over 4
-
-=item redoop
-
-=item nextop
-
-=item lastop
-
-=back
-
-=head2 B::COP METHODS
-
-=over 4
-
-=item label
-
-=item stash
-
-=item file
-
-=item cop_seq
-
-=item arybase
-
-=item line
-
-=back
-
-=head1 FUNCTIONS EXPORTED BY C<B>
-
-The C<B> module exports a variety of functions: some are simple
-utility functions, others provide a Perl program with a way to
-get an initial "handle" on an internal object.
-
-=over 4
-
-=item main_cv
-
-Return the (faked) CV corresponding to the main part of the Perl
-program.
-
-=item init_av
-
-Returns the AV object (i.e. in class B::AV) representing INIT blocks.
-
-=item main_root
-
-Returns the root op (i.e. an object in the appropriate B::OP-derived
-class) of the main part of the Perl program.
-
-=item main_start
-
-Returns the starting op of the main part of the Perl program.
-
-=item comppadlist
-
-Returns the AV object (i.e. in class B::AV) of the global comppadlist.
-
-=item sv_undef
-
-Returns the SV object corresponding to the C variable C<sv_undef>.
-
-=item sv_yes
-
-Returns the SV object corresponding to the C variable C<sv_yes>.
-
-=item sv_no
-
-Returns the SV object corresponding to the C variable C<sv_no>.
-
-=item amagic_generation
-
-Returns the SV object corresponding to the C variable C<amagic_generation>.
-
-=item walkoptree(OP, METHOD)
-
-Does a tree-walk of the syntax tree based at OP and calls METHOD on
-each op it visits. Each node is visited before its children. If
-C<walkoptree_debug> (q.v.) has been called to turn debugging on then
-the method C<walkoptree_debug> is called on each op before METHOD is
-called.
-
-=item walkoptree_debug(DEBUG)
-
-Returns the current debugging flag for C<walkoptree>. If the optional
-DEBUG argument is non-zero, it sets the debugging flag to that. See
-the description of C<walkoptree> above for what the debugging flag
-does.
-
-=item walksymtable(SYMREF, METHOD, RECURSE)
-
-Walk the symbol table starting at SYMREF and call METHOD on each
-symbol visited. When the walk reached package symbols "Foo::" it
-invokes RECURSE and only recurses into the package if that sub
-returns true.
-
-=item svref_2object(SV)
-
-Takes any Perl variable and turns it into an object in the
-appropriate B::OP-derived or B::SV-derived class. Apart from functions
-such as C<main_root>, this is the primary way to get an initial
-"handle" on a internal perl data structure which can then be followed
-with the other access methods.
-
-=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 the
-internal 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_c
-
-Does the equivalent of the C<-c> command-line option. Obviously, this
-is 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 can
-be used as a string in C source code.
-
-=item class(OBJ)
-
-Returns the class of an object without the part of the classname
-preceding the first "::". This is used to turn "B::UNOP" into
-"UNOP" for example.
-
-=item threadsv_names
-
-In a perl compiled for threads, this returns a list of the special
-per-thread threadsv variables.
-
-=back
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B.xs b/contrib/perl5/ext/B/B.xs
deleted file mode 100644
index 1005747..0000000
--- a/contrib/perl5/ext/B/B.xs
+++ /dev/null
@@ -1,1285 +0,0 @@
-/* B.xs
- *
- * Copyright (c) 1996 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.
- *
- */
-
-#define PERL_NO_GET_CONTEXT
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-#ifdef PERL_OBJECT
-#undef PL_op_name
-#undef PL_opargs
-#undef PL_op_desc
-#define PL_op_name (get_op_names())
-#define PL_opargs (get_opargs())
-#define PL_op_desc (get_op_descs())
-#endif
-
-#ifdef PerlIO
-typedef PerlIO * InputStream;
-#else
-typedef FILE * InputStream;
-#endif
-
-
-static char *svclassnames[] = {
- "B::NULL",
- "B::IV",
- "B::NV",
- "B::RV",
- "B::PV",
- "B::PVIV",
- "B::PVNV",
- "B::PVMG",
- "B::BM",
- "B::PVLV",
- "B::AV",
- "B::HV",
- "B::CV",
- "B::GV",
- "B::FM",
- "B::IO",
-};
-
-typedef enum {
- OPc_NULL, /* 0 */
- OPc_BASEOP, /* 1 */
- OPc_UNOP, /* 2 */
- OPc_BINOP, /* 3 */
- OPc_LOGOP, /* 4 */
- OPc_LISTOP, /* 5 */
- OPc_PMOP, /* 6 */
- OPc_SVOP, /* 7 */
- OPc_PADOP, /* 8 */
- OPc_PVOP, /* 9 */
- OPc_CVOP, /* 10 */
- OPc_LOOP, /* 11 */
- OPc_COP /* 12 */
-} opclass;
-
-static char *opclassnames[] = {
- "B::NULL",
- "B::OP",
- "B::UNOP",
- "B::BINOP",
- "B::LOGOP",
- "B::LISTOP",
- "B::PMOP",
- "B::SVOP",
- "B::PADOP",
- "B::PVOP",
- "B::CVOP",
- "B::LOOP",
- "B::COP"
-};
-
-static int walkoptree_debug = 0; /* Flag for walkoptree debug hook */
-
-static SV *specialsv_list[6];
-
-static opclass
-cc_opclass(pTHX_ OP *o)
-{
- if (!o)
- return OPc_NULL;
-
- if (o->op_type == 0)
- return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
-
- if (o->op_type == OP_SASSIGN)
- return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
-
-#ifdef USE_ITHREADS
- if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
- return OPc_PADOP;
-#endif
-
- switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
- case OA_BASEOP:
- return OPc_BASEOP;
-
- case OA_UNOP:
- return OPc_UNOP;
-
- case OA_BINOP:
- return OPc_BINOP;
-
- case OA_LOGOP:
- return OPc_LOGOP;
-
- case OA_LISTOP:
- return OPc_LISTOP;
-
- case OA_PMOP:
- return OPc_PMOP;
-
- case OA_SVOP:
- return OPc_SVOP;
-
- case OA_PADOP:
- return OPc_PADOP;
-
- case OA_PVOP_OR_SVOP:
- /*
- * Character translations (tr///) are usually a PVOP, keeping a
- * pointer to a table of shorts used to look up translations.
- * Under utf8, however, a simple table isn't practical; instead,
- * the OP is an SVOP, and the SV is a reference to a swash
- * (i.e., an RV pointing to an HV).
- */
- return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
- ? OPc_SVOP : OPc_PVOP;
-
- case OA_LOOP:
- return OPc_LOOP;
-
- case OA_COP:
- return OPc_COP;
-
- case OA_BASEOP_OR_UNOP:
- /*
- * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
- * whether parens were seen. perly.y uses OPf_SPECIAL to
- * signal whether a BASEOP had empty parens or none.
- * Some other UNOPs are created later, though, so the best
- * test is OPf_KIDS, which is set in newUNOP.
- */
- return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
-
- case OA_FILESTATOP:
- /*
- * The file stat OPs are created via UNI(OP_foo) in toke.c but use
- * the OPf_REF flag to distinguish between OP types instead of the
- * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
- * return OPc_UNOP so that walkoptree can find our children. If
- * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
- * (no argument to the operator) it's an OP; with OPf_REF set it's
- * an SVOP (and op_sv is the GV for the filehandle argument).
- */
- return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
-#ifdef USE_ITHREADS
- (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
-#else
- (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
-#endif
- case OA_LOOPEXOP:
- /*
- * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
- * label was omitted (in which case it's a BASEOP) or else a term was
- * seen. In this last case, all except goto are definitely PVOP but
- * goto is either a PVOP (with an ordinary constant label), an UNOP
- * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
- * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
- * get set.
- */
- if (o->op_flags & OPf_STACKED)
- return OPc_UNOP;
- else if (o->op_flags & OPf_SPECIAL)
- return OPc_BASEOP;
- else
- return OPc_PVOP;
- }
- warn("can't determine class of operator %s, assuming BASEOP\n",
- PL_op_name[o->op_type]);
- return OPc_BASEOP;
-}
-
-static char *
-cc_opclassname(pTHX_ OP *o)
-{
- return opclassnames[cc_opclass(aTHX_ o)];
-}
-
-static SV *
-make_sv_object(pTHX_ SV *arg, SV *sv)
-{
- char *type = 0;
- IV iv;
-
- for (iv = 0; iv < sizeof(specialsv_list)/sizeof(SV*); iv++) {
- if (sv == specialsv_list[iv]) {
- type = "B::SPECIAL";
- break;
- }
- }
- if (!type) {
- type = svclassnames[SvTYPE(sv)];
- iv = PTR2IV(sv);
- }
- sv_setiv(newSVrv(arg, type), iv);
- return arg;
-}
-
-static SV *
-make_mg_object(pTHX_ SV *arg, MAGIC *mg)
-{
- sv_setiv(newSVrv(arg, "B::MAGIC"), PTR2IV(mg));
- return arg;
-}
-
-static SV *
-cstring(pTHX_ SV *sv)
-{
- SV *sstr = newSVpvn("", 0);
- STRLEN len;
- char *s;
-
- if (!SvOK(sv))
- sv_setpvn(sstr, "0", 1);
- else
- {
- /* XXX Optimise? */
- s = SvPV(sv, len);
- sv_catpv(sstr, "\"");
- for (; len; len--, s++)
- {
- /* At least try a little for readability */
- if (*s == '"')
- sv_catpv(sstr, "\\\"");
- else if (*s == '\\')
- sv_catpv(sstr, "\\\\");
- else if (*s >= ' ' && *s < 127) /* XXX not portable */
- sv_catpvn(sstr, s, 1);
- else if (*s == '\n')
- sv_catpv(sstr, "\\n");
- else if (*s == '\r')
- sv_catpv(sstr, "\\r");
- else if (*s == '\t')
- sv_catpv(sstr, "\\t");
- else if (*s == '\a')
- sv_catpv(sstr, "\\a");
- else if (*s == '\b')
- sv_catpv(sstr, "\\b");
- else if (*s == '\f')
- sv_catpv(sstr, "\\f");
- else if (*s == '\v')
- sv_catpv(sstr, "\\v");
- else
- {
- /* no trigraph support */
- char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */
- /* Don't want promotion of a signed -1 char in sprintf args */
- unsigned char c = (unsigned char) *s;
- sprintf(escbuff, "\\%03o", c);
- sv_catpv(sstr, escbuff);
- }
- /* XXX Add line breaks if string is long */
- }
- sv_catpv(sstr, "\"");
- }
- return sstr;
-}
-
-static SV *
-cchar(pTHX_ SV *sv)
-{
- SV *sstr = newSVpvn("'", 1);
- STRLEN n_a;
- char *s = SvPV(sv, n_a);
-
- if (*s == '\'')
- sv_catpv(sstr, "\\'");
- else if (*s == '\\')
- sv_catpv(sstr, "\\\\");
- else if (*s >= ' ' && *s < 127) /* XXX not portable */
- sv_catpvn(sstr, s, 1);
- else if (*s == '\n')
- sv_catpv(sstr, "\\n");
- else if (*s == '\r')
- sv_catpv(sstr, "\\r");
- else if (*s == '\t')
- sv_catpv(sstr, "\\t");
- else if (*s == '\a')
- sv_catpv(sstr, "\\a");
- else if (*s == '\b')
- sv_catpv(sstr, "\\b");
- else if (*s == '\f')
- sv_catpv(sstr, "\\f");
- else if (*s == '\v')
- sv_catpv(sstr, "\\v");
- else
- {
- /* no trigraph support */
- char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */
- /* Don't want promotion of a signed -1 char in sprintf args */
- unsigned char c = (unsigned char) *s;
- sprintf(escbuff, "\\%03o", c);
- sv_catpv(sstr, escbuff);
- }
- sv_catpv(sstr, "'");
- return sstr;
-}
-
-void
-walkoptree(pTHX_ SV *opsv, char *method)
-{
- dSP;
- OP *o;
-
- if (!SvROK(opsv))
- croak("opsv is not a reference");
- opsv = sv_mortalcopy(opsv);
- o = INT2PTR(OP*,SvIV((SV*)SvRV(opsv)));
- if (walkoptree_debug) {
- PUSHMARK(sp);
- XPUSHs(opsv);
- PUTBACK;
- perl_call_method("walkoptree_debug", G_DISCARD);
- }
- PUSHMARK(sp);
- XPUSHs(opsv);
- PUTBACK;
- perl_call_method(method, G_DISCARD);
- if (o && (o->op_flags & OPf_KIDS)) {
- OP *kid;
- for (kid = ((UNOP*)o)->op_first; kid; kid = kid->op_sibling) {
- /* Use the same opsv. Rely on methods not to mess it up. */
- sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid));
- walkoptree(aTHX_ opsv, method);
- }
- }
-}
-
-typedef OP *B__OP;
-typedef UNOP *B__UNOP;
-typedef BINOP *B__BINOP;
-typedef LOGOP *B__LOGOP;
-typedef LISTOP *B__LISTOP;
-typedef PMOP *B__PMOP;
-typedef SVOP *B__SVOP;
-typedef PADOP *B__PADOP;
-typedef PVOP *B__PVOP;
-typedef LOOP *B__LOOP;
-typedef COP *B__COP;
-
-typedef SV *B__SV;
-typedef SV *B__IV;
-typedef SV *B__PV;
-typedef SV *B__NV;
-typedef SV *B__PVMG;
-typedef SV *B__PVLV;
-typedef SV *B__BM;
-typedef SV *B__RV;
-typedef AV *B__AV;
-typedef HV *B__HV;
-typedef CV *B__CV;
-typedef GV *B__GV;
-typedef IO *B__IO;
-
-typedef MAGIC *B__MAGIC;
-
-MODULE = B PACKAGE = B PREFIX = B_
-
-PROTOTYPES: DISABLE
-
-BOOT:
-{
- HV *stash = gv_stashpvn("B", 1, TRUE);
- AV *export_ok = perl_get_av("B::EXPORT_OK",TRUE);
- specialsv_list[0] = Nullsv;
- specialsv_list[1] = &PL_sv_undef;
- specialsv_list[2] = &PL_sv_yes;
- specialsv_list[3] = &PL_sv_no;
- specialsv_list[4] = pWARN_ALL;
- specialsv_list[5] = pWARN_NONE;
-#include "defsubs.h"
-}
-
-#define B_main_cv() PL_main_cv
-#define B_init_av() PL_initav
-#define B_begin_av() PL_beginav_save
-#define B_end_av() PL_endav
-#define B_main_root() PL_main_root
-#define B_main_start() PL_main_start
-#define B_amagic_generation() PL_amagic_generation
-#define B_comppadlist() (PL_main_cv ? CvPADLIST(PL_main_cv) : CvPADLIST(PL_compcv))
-#define B_sv_undef() &PL_sv_undef
-#define B_sv_yes() &PL_sv_yes
-#define B_sv_no() &PL_sv_no
-
-B::AV
-B_init_av()
-
-B::AV
-B_begin_av()
-
-B::AV
-B_end_av()
-
-B::CV
-B_main_cv()
-
-B::OP
-B_main_root()
-
-B::OP
-B_main_start()
-
-long
-B_amagic_generation()
-
-B::AV
-B_comppadlist()
-
-B::SV
-B_sv_undef()
-
-B::SV
-B_sv_yes()
-
-B::SV
-B_sv_no()
-
-MODULE = B PACKAGE = B
-
-
-void
-walkoptree(opsv, method)
- SV * opsv
- char * method
- CODE:
- walkoptree(aTHX_ opsv, method);
-
-int
-walkoptree_debug(...)
- CODE:
- RETVAL = walkoptree_debug;
- if (items > 0 && SvTRUE(ST(1)))
- walkoptree_debug = 1;
- OUTPUT:
- RETVAL
-
-#define address(sv) PTR2IV(sv)
-
-IV
-address(sv)
- SV * sv
-
-B::SV
-svref_2object(sv)
- SV * sv
- CODE:
- if (!SvROK(sv))
- croak("argument is not a reference");
- RETVAL = (SV*)SvRV(sv);
- OUTPUT:
- RETVAL
-
-void
-opnumber(name)
-char * name
-CODE:
-{
- int i;
- IV result = -1;
- ST(0) = sv_newmortal();
- if (strncmp(name,"pp_",3) == 0)
- name += 3;
- for (i = 0; i < PL_maxo; i++)
- {
- if (strcmp(name, PL_op_name[i]) == 0)
- {
- result = i;
- break;
- }
- }
- sv_setiv(ST(0),result);
-}
-
-void
-ppname(opnum)
- int opnum
- CODE:
- ST(0) = sv_newmortal();
- if (opnum >= 0 && opnum < PL_maxo) {
- sv_setpvn(ST(0), "pp_", 3);
- sv_catpv(ST(0), PL_op_name[opnum]);
- }
-
-void
-hash(sv)
- SV * sv
- CODE:
- char *s;
- STRLEN len;
- U32 hash = 0;
- char hexhash[19]; /* must fit "0xffffffffffffffff" plus trailing \0 */
- s = SvPV(sv, len);
- PERL_HASH(hash, s, len);
- sprintf(hexhash, "0x%"UVxf, (UV)hash);
- ST(0) = sv_2mortal(newSVpv(hexhash, 0));
-
-#define cast_I32(foo) (I32)foo
-IV
-cast_I32(i)
- IV i
-
-void
-minus_c()
- CODE:
- PL_minus_c = TRUE;
-
-void
-save_BEGINs()
- CODE:
- PL_minus_c |= 0x10;
-
-SV *
-cstring(sv)
- SV * sv
- CODE:
- RETVAL = cstring(aTHX_ sv);
- OUTPUT:
- RETVAL
-
-SV *
-cchar(sv)
- SV * sv
- CODE:
- RETVAL = cchar(aTHX_ sv);
- OUTPUT:
- RETVAL
-
-void
-threadsv_names()
- PPCODE:
-#ifdef USE_THREADS
- int i;
- STRLEN len = strlen(PL_threadsv_names);
-
- EXTEND(sp, len);
- for (i = 0; i < len; i++)
- PUSHs(sv_2mortal(newSVpvn(&PL_threadsv_names[i], 1)));
-#endif
-
-
-#define OP_next(o) o->op_next
-#define OP_sibling(o) o->op_sibling
-#define OP_desc(o) PL_op_desc[o->op_type]
-#define OP_targ(o) o->op_targ
-#define OP_type(o) o->op_type
-#define OP_seq(o) o->op_seq
-#define OP_flags(o) o->op_flags
-#define OP_private(o) o->op_private
-
-MODULE = B PACKAGE = B::OP PREFIX = OP_
-
-B::OP
-OP_next(o)
- B::OP o
-
-B::OP
-OP_sibling(o)
- B::OP o
-
-char *
-OP_name(o)
- B::OP o
- CODE:
- RETVAL = PL_op_name[o->op_type];
- OUTPUT:
- RETVAL
-
-
-void
-OP_ppaddr(o)
- B::OP o
- PREINIT:
- int i;
- SV *sv = sv_newmortal();
- CODE:
- sv_setpvn(sv, "PL_ppaddr[OP_", 13);
- sv_catpv(sv, PL_op_name[o->op_type]);
- for (i=13; i<SvCUR(sv); ++i)
- SvPVX(sv)[i] = toUPPER(SvPVX(sv)[i]);
- sv_catpv(sv, "]");
- ST(0) = sv;
-
-char *
-OP_desc(o)
- B::OP o
-
-PADOFFSET
-OP_targ(o)
- B::OP o
-
-U16
-OP_type(o)
- B::OP o
-
-U16
-OP_seq(o)
- B::OP o
-
-U8
-OP_flags(o)
- B::OP o
-
-U8
-OP_private(o)
- B::OP o
-
-#define UNOP_first(o) o->op_first
-
-MODULE = B PACKAGE = B::UNOP PREFIX = UNOP_
-
-B::OP
-UNOP_first(o)
- B::UNOP o
-
-#define BINOP_last(o) o->op_last
-
-MODULE = B PACKAGE = B::BINOP PREFIX = BINOP_
-
-B::OP
-BINOP_last(o)
- B::BINOP o
-
-#define LOGOP_other(o) o->op_other
-
-MODULE = B PACKAGE = B::LOGOP PREFIX = LOGOP_
-
-B::OP
-LOGOP_other(o)
- B::LOGOP o
-
-MODULE = B PACKAGE = B::LISTOP PREFIX = LISTOP_
-
-U32
-LISTOP_children(o)
- B::LISTOP o
- OP * kid = NO_INIT
- int i = NO_INIT
- CODE:
- i = 0;
- for (kid = o->op_first; kid; kid = kid->op_sibling)
- i++;
- RETVAL = i;
- OUTPUT:
- RETVAL
-
-#define PMOP_pmreplroot(o) o->op_pmreplroot
-#define PMOP_pmreplstart(o) o->op_pmreplstart
-#define PMOP_pmnext(o) o->op_pmnext
-#define PMOP_pmregexp(o) o->op_pmregexp
-#define PMOP_pmflags(o) o->op_pmflags
-#define PMOP_pmpermflags(o) o->op_pmpermflags
-
-MODULE = B PACKAGE = B::PMOP PREFIX = PMOP_
-
-void
-PMOP_pmreplroot(o)
- B::PMOP o
- OP * root = NO_INIT
- CODE:
- ST(0) = sv_newmortal();
- root = o->op_pmreplroot;
- /* OP_PUSHRE stores an SV* instead of an OP* in op_pmreplroot */
- if (o->op_type == OP_PUSHRE) {
- sv_setiv(newSVrv(ST(0), root ?
- svclassnames[SvTYPE((SV*)root)] : "B::SV"),
- PTR2IV(root));
- }
- else {
- sv_setiv(newSVrv(ST(0), cc_opclassname(aTHX_ root)), PTR2IV(root));
- }
-
-B::OP
-PMOP_pmreplstart(o)
- B::PMOP o
-
-B::PMOP
-PMOP_pmnext(o)
- B::PMOP o
-
-U16
-PMOP_pmflags(o)
- B::PMOP o
-
-U16
-PMOP_pmpermflags(o)
- B::PMOP o
-
-void
-PMOP_precomp(o)
- B::PMOP o
- REGEXP * rx = NO_INIT
- CODE:
- ST(0) = sv_newmortal();
- rx = o->op_pmregexp;
- if (rx)
- sv_setpvn(ST(0), rx->precomp, rx->prelen);
-
-#define SVOP_sv(o) cSVOPo->op_sv
-#define SVOP_gv(o) ((GV*)cSVOPo->op_sv)
-
-MODULE = B PACKAGE = B::SVOP PREFIX = SVOP_
-
-B::SV
-SVOP_sv(o)
- B::SVOP o
-
-B::GV
-SVOP_gv(o)
- B::SVOP o
-
-#define PADOP_padix(o) o->op_padix
-#define PADOP_sv(o) (o->op_padix ? PL_curpad[o->op_padix] : Nullsv)
-#define PADOP_gv(o) ((o->op_padix \
- && SvTYPE(PL_curpad[o->op_padix]) == SVt_PVGV) \
- ? (GV*)PL_curpad[o->op_padix] : Nullgv)
-
-MODULE = B PACKAGE = B::PADOP PREFIX = PADOP_
-
-PADOFFSET
-PADOP_padix(o)
- B::PADOP o
-
-B::SV
-PADOP_sv(o)
- B::PADOP o
-
-B::GV
-PADOP_gv(o)
- B::PADOP o
-
-MODULE = B PACKAGE = B::PVOP PREFIX = PVOP_
-
-void
-PVOP_pv(o)
- B::PVOP o
- CODE:
- /*
- * OP_TRANS uses op_pv to point to a table of 256 shorts
- * whereas other PVOPs point to a null terminated string.
- */
- ST(0) = sv_2mortal(newSVpv(o->op_pv, (o->op_type == OP_TRANS) ?
- 256 * sizeof(short) : 0));
-
-#define LOOP_redoop(o) o->op_redoop
-#define LOOP_nextop(o) o->op_nextop
-#define LOOP_lastop(o) o->op_lastop
-
-MODULE = B PACKAGE = B::LOOP PREFIX = LOOP_
-
-
-B::OP
-LOOP_redoop(o)
- B::LOOP o
-
-B::OP
-LOOP_nextop(o)
- B::LOOP o
-
-B::OP
-LOOP_lastop(o)
- B::LOOP o
-
-#define COP_label(o) o->cop_label
-#define COP_stashpv(o) CopSTASHPV(o)
-#define COP_stash(o) CopSTASH(o)
-#define COP_file(o) CopFILE(o)
-#define COP_cop_seq(o) o->cop_seq
-#define COP_arybase(o) o->cop_arybase
-#define COP_line(o) CopLINE(o)
-#define COP_warnings(o) o->cop_warnings
-
-MODULE = B PACKAGE = B::COP PREFIX = COP_
-
-char *
-COP_label(o)
- B::COP o
-
-char *
-COP_stashpv(o)
- B::COP o
-
-B::HV
-COP_stash(o)
- B::COP o
-
-char *
-COP_file(o)
- B::COP o
-
-U32
-COP_cop_seq(o)
- B::COP o
-
-I32
-COP_arybase(o)
- B::COP o
-
-U16
-COP_line(o)
- B::COP o
-
-B::SV
-COP_warnings(o)
- B::COP o
-
-MODULE = B PACKAGE = B::SV PREFIX = Sv
-
-U32
-SvREFCNT(sv)
- B::SV sv
-
-U32
-SvFLAGS(sv)
- B::SV sv
-
-MODULE = B PACKAGE = B::IV PREFIX = Sv
-
-IV
-SvIV(sv)
- B::IV sv
-
-IV
-SvIVX(sv)
- B::IV sv
-
-UV
-SvUVX(sv)
- B::IV sv
-
-
-MODULE = B PACKAGE = B::IV
-
-#define needs64bits(sv) ((I32)SvIVX(sv) != SvIVX(sv))
-
-int
-needs64bits(sv)
- B::IV sv
-
-void
-packiv(sv)
- B::IV sv
- CODE:
- if (sizeof(IV) == 8) {
- U32 wp[2];
- IV iv = SvIVX(sv);
- /*
- * The following way of spelling 32 is to stop compilers on
- * 32-bit architectures from moaning about the shift count
- * being >= the width of the type. Such architectures don't
- * reach this code anyway (unless sizeof(IV) > 8 but then
- * everything else breaks too so I'm not fussed at the moment).
- */
-#ifdef UV_IS_QUAD
- wp[0] = htonl(((UV)iv) >> (sizeof(UV)*4));
-#else
- wp[0] = htonl(((U32)iv) >> (sizeof(UV)*4));
-#endif
- wp[1] = htonl(iv & 0xffffffff);
- ST(0) = sv_2mortal(newSVpvn((char *)wp, 8));
- } else {
- U32 w = htonl((U32)SvIVX(sv));
- ST(0) = sv_2mortal(newSVpvn((char *)&w, 4));
- }
-
-MODULE = B PACKAGE = B::NV PREFIX = Sv
-
-NV
-SvNV(sv)
- B::NV sv
-
-NV
-SvNVX(sv)
- B::NV sv
-
-MODULE = B PACKAGE = B::RV PREFIX = Sv
-
-B::SV
-SvRV(sv)
- B::RV sv
-
-MODULE = B PACKAGE = B::PV PREFIX = Sv
-
-char*
-SvPVX(sv)
- B::PV sv
-
-void
-SvPV(sv)
- B::PV sv
- CODE:
- ST(0) = sv_newmortal();
- sv_setpvn(ST(0), SvPVX(sv), SvCUR(sv));
-
-STRLEN
-SvLEN(sv)
- B::PV sv
-
-STRLEN
-SvCUR(sv)
- B::PV sv
-
-MODULE = B PACKAGE = B::PVMG PREFIX = Sv
-
-void
-SvMAGIC(sv)
- B::PVMG sv
- MAGIC * mg = NO_INIT
- PPCODE:
- for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic)
- XPUSHs(make_mg_object(aTHX_ sv_newmortal(), mg));
-
-MODULE = B PACKAGE = B::PVMG
-
-B::HV
-SvSTASH(sv)
- B::PVMG sv
-
-#define MgMOREMAGIC(mg) mg->mg_moremagic
-#define MgPRIVATE(mg) mg->mg_private
-#define MgTYPE(mg) mg->mg_type
-#define MgFLAGS(mg) mg->mg_flags
-#define MgOBJ(mg) mg->mg_obj
-#define MgLENGTH(mg) mg->mg_len
-
-MODULE = B PACKAGE = B::MAGIC PREFIX = Mg
-
-B::MAGIC
-MgMOREMAGIC(mg)
- B::MAGIC mg
-
-U16
-MgPRIVATE(mg)
- B::MAGIC mg
-
-char
-MgTYPE(mg)
- B::MAGIC mg
-
-U8
-MgFLAGS(mg)
- B::MAGIC mg
-
-B::SV
-MgOBJ(mg)
- B::MAGIC mg
-
-I32
-MgLENGTH(mg)
- B::MAGIC mg
-
-void
-MgPTR(mg)
- B::MAGIC mg
- CODE:
- ST(0) = sv_newmortal();
- if (mg->mg_ptr){
- if (mg->mg_len >= 0){
- sv_setpvn(ST(0), mg->mg_ptr, mg->mg_len);
- } else {
- if (mg->mg_len == HEf_SVKEY)
- sv_setsv(ST(0),newRV((SV*)mg->mg_ptr));
- }
- }
-
-MODULE = B PACKAGE = B::PVLV PREFIX = Lv
-
-U32
-LvTARGOFF(sv)
- B::PVLV sv
-
-U32
-LvTARGLEN(sv)
- B::PVLV sv
-
-char
-LvTYPE(sv)
- B::PVLV sv
-
-B::SV
-LvTARG(sv)
- B::PVLV sv
-
-MODULE = B PACKAGE = B::BM PREFIX = Bm
-
-I32
-BmUSEFUL(sv)
- B::BM sv
-
-U16
-BmPREVIOUS(sv)
- B::BM sv
-
-U8
-BmRARE(sv)
- B::BM sv
-
-void
-BmTABLE(sv)
- B::BM sv
- STRLEN len = NO_INIT
- char * str = NO_INIT
- CODE:
- str = SvPV(sv, len);
- /* Boyer-Moore table is just after string and its safety-margin \0 */
- ST(0) = sv_2mortal(newSVpvn(str + len + 1, 256));
-
-MODULE = B PACKAGE = B::GV PREFIX = Gv
-
-void
-GvNAME(gv)
- B::GV gv
- CODE:
- ST(0) = sv_2mortal(newSVpvn(GvNAME(gv), GvNAMELEN(gv)));
-
-bool
-is_empty(gv)
- B::GV gv
- CODE:
- RETVAL = GvGP(gv) == Null(GP*);
- OUTPUT:
- RETVAL
-
-B::HV
-GvSTASH(gv)
- B::GV gv
-
-B::SV
-GvSV(gv)
- B::GV gv
-
-B::IO
-GvIO(gv)
- B::GV gv
-
-B::CV
-GvFORM(gv)
- B::GV gv
-
-B::AV
-GvAV(gv)
- B::GV gv
-
-B::HV
-GvHV(gv)
- B::GV gv
-
-B::GV
-GvEGV(gv)
- B::GV gv
-
-B::CV
-GvCV(gv)
- B::GV gv
-
-U32
-GvCVGEN(gv)
- B::GV gv
-
-U16
-GvLINE(gv)
- B::GV gv
-
-char *
-GvFILE(gv)
- B::GV gv
-
-B::GV
-GvFILEGV(gv)
- B::GV gv
-
-MODULE = B PACKAGE = B::GV
-
-U32
-GvREFCNT(gv)
- B::GV gv
-
-U8
-GvFLAGS(gv)
- B::GV gv
-
-MODULE = B PACKAGE = B::IO PREFIX = Io
-
-long
-IoLINES(io)
- B::IO io
-
-long
-IoPAGE(io)
- B::IO io
-
-long
-IoPAGE_LEN(io)
- B::IO io
-
-long
-IoLINES_LEFT(io)
- B::IO io
-
-char *
-IoTOP_NAME(io)
- B::IO io
-
-B::GV
-IoTOP_GV(io)
- B::IO io
-
-char *
-IoFMT_NAME(io)
- B::IO io
-
-B::GV
-IoFMT_GV(io)
- B::IO io
-
-char *
-IoBOTTOM_NAME(io)
- B::IO io
-
-B::GV
-IoBOTTOM_GV(io)
- B::IO io
-
-short
-IoSUBPROCESS(io)
- B::IO io
-
-MODULE = B PACKAGE = B::IO
-
-char
-IoTYPE(io)
- B::IO io
-
-U8
-IoFLAGS(io)
- B::IO io
-
-MODULE = B PACKAGE = B::AV PREFIX = Av
-
-SSize_t
-AvFILL(av)
- B::AV av
-
-SSize_t
-AvMAX(av)
- B::AV av
-
-#define AvOFF(av) ((XPVAV*)SvANY(av))->xof_off
-
-IV
-AvOFF(av)
- B::AV av
-
-void
-AvARRAY(av)
- B::AV av
- PPCODE:
- if (AvFILL(av) >= 0) {
- SV **svp = AvARRAY(av);
- I32 i;
- for (i = 0; i <= AvFILL(av); i++)
- XPUSHs(make_sv_object(aTHX_ sv_newmortal(), svp[i]));
- }
-
-MODULE = B PACKAGE = B::AV
-
-U8
-AvFLAGS(av)
- B::AV av
-
-MODULE = B PACKAGE = B::CV PREFIX = Cv
-
-B::HV
-CvSTASH(cv)
- B::CV cv
-
-B::OP
-CvSTART(cv)
- B::CV cv
-
-B::OP
-CvROOT(cv)
- B::CV cv
-
-B::GV
-CvGV(cv)
- B::CV cv
-
-char *
-CvFILE(cv)
- B::CV cv
-
-long
-CvDEPTH(cv)
- B::CV cv
-
-B::AV
-CvPADLIST(cv)
- B::CV cv
-
-B::CV
-CvOUTSIDE(cv)
- B::CV cv
-
-void
-CvXSUB(cv)
- B::CV cv
- CODE:
- ST(0) = sv_2mortal(newSViv(PTR2IV(CvXSUB(cv))));
-
-
-void
-CvXSUBANY(cv)
- B::CV cv
- CODE:
- ST(0) = sv_2mortal(newSViv(CvXSUBANY(cv).any_iv));
-
-MODULE = B PACKAGE = B::CV
-
-U16
-CvFLAGS(cv)
- B::CV cv
-
-
-MODULE = B PACKAGE = B::HV PREFIX = Hv
-
-STRLEN
-HvFILL(hv)
- B::HV hv
-
-STRLEN
-HvMAX(hv)
- B::HV hv
-
-I32
-HvKEYS(hv)
- B::HV hv
-
-I32
-HvRITER(hv)
- B::HV hv
-
-char *
-HvNAME(hv)
- B::HV hv
-
-B::PMOP
-HvPMROOT(hv)
- B::HV hv
-
-void
-HvARRAY(hv)
- B::HV hv
- PPCODE:
- if (HvKEYS(hv) > 0) {
- SV *sv;
- char *key;
- I32 len;
- (void)hv_iterinit(hv);
- EXTEND(sp, HvKEYS(hv) * 2);
- while ((sv = hv_iternextsv(hv, &key, &len))) {
- PUSHs(newSVpvn(key, len));
- PUSHs(make_sv_object(aTHX_ sv_newmortal(), sv));
- }
- }
diff --git a/contrib/perl5/ext/B/B/Asmdata.pm b/contrib/perl5/ext/B/B/Asmdata.pm
deleted file mode 100644
index dc176be..0000000
--- a/contrib/perl5/ext/B/B/Asmdata.pm
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# Copyright (c) 1996-1999 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.
-#
-#
-#
-# This file is autogenerated from bytecode.pl. Changes made here will be lost.
-#
-package B::Asmdata;
-use Exporter;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(%insn_data @insn_name @optype @specialsv_name);
-our(%insn_data, @insn_name, @optype, @specialsv_name);
-
-@optype = qw(OP UNOP BINOP LOGOP LISTOP PMOP SVOP PADOP PVOP LOOP COP);
-@specialsv_name = qw(Nullsv &PL_sv_undef &PL_sv_yes &PL_sv_no pWARN_ALL pWARN_NONE);
-
-# XXX insn_data is initialised this way because with a large
-# %insn_data = (foo => [...], bar => [...], ...) initialiser
-# I get a hard-to-track-down stack underflow and segfault.
-$insn_data{comment} = [35, \&PUT_comment_t, "GET_comment_t"];
-$insn_data{nop} = [10, \&PUT_none, "GET_none"];
-$insn_data{ret} = [0, \&PUT_none, "GET_none"];
-$insn_data{ldsv} = [1, \&PUT_svindex, "GET_svindex"];
-$insn_data{ldop} = [2, \&PUT_opindex, "GET_opindex"];
-$insn_data{stsv} = [3, \&PUT_U32, "GET_U32"];
-$insn_data{stop} = [4, \&PUT_U32, "GET_U32"];
-$insn_data{stpv} = [5, \&PUT_U32, "GET_U32"];
-$insn_data{ldspecsv} = [6, \&PUT_U8, "GET_U8"];
-$insn_data{newsv} = [7, \&PUT_U8, "GET_U8"];
-$insn_data{newop} = [8, \&PUT_U8, "GET_U8"];
-$insn_data{newopn} = [9, \&PUT_U8, "GET_U8"];
-$insn_data{newpv} = [11, \&PUT_PV, "GET_PV"];
-$insn_data{pv_cur} = [12, \&PUT_U32, "GET_U32"];
-$insn_data{pv_free} = [13, \&PUT_none, "GET_none"];
-$insn_data{sv_upgrade} = [14, \&PUT_U8, "GET_U8"];
-$insn_data{sv_refcnt} = [15, \&PUT_U32, "GET_U32"];
-$insn_data{sv_refcnt_add} = [16, \&PUT_I32, "GET_I32"];
-$insn_data{sv_flags} = [17, \&PUT_U32, "GET_U32"];
-$insn_data{xrv} = [18, \&PUT_svindex, "GET_svindex"];
-$insn_data{xpv} = [19, \&PUT_none, "GET_none"];
-$insn_data{xiv32} = [20, \&PUT_I32, "GET_I32"];
-$insn_data{xiv64} = [21, \&PUT_IV64, "GET_IV64"];
-$insn_data{xnv} = [22, \&PUT_NV, "GET_NV"];
-$insn_data{xlv_targoff} = [23, \&PUT_U32, "GET_U32"];
-$insn_data{xlv_targlen} = [24, \&PUT_U32, "GET_U32"];
-$insn_data{xlv_targ} = [25, \&PUT_svindex, "GET_svindex"];
-$insn_data{xlv_type} = [26, \&PUT_U8, "GET_U8"];
-$insn_data{xbm_useful} = [27, \&PUT_I32, "GET_I32"];
-$insn_data{xbm_previous} = [28, \&PUT_U16, "GET_U16"];
-$insn_data{xbm_rare} = [29, \&PUT_U8, "GET_U8"];
-$insn_data{xfm_lines} = [30, \&PUT_I32, "GET_I32"];
-$insn_data{xio_lines} = [31, \&PUT_I32, "GET_I32"];
-$insn_data{xio_page} = [32, \&PUT_I32, "GET_I32"];
-$insn_data{xio_page_len} = [33, \&PUT_I32, "GET_I32"];
-$insn_data{xio_lines_left} = [34, \&PUT_I32, "GET_I32"];
-$insn_data{xio_top_name} = [36, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{xio_top_gv} = [37, \&PUT_svindex, "GET_svindex"];
-$insn_data{xio_fmt_name} = [38, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{xio_fmt_gv} = [39, \&PUT_svindex, "GET_svindex"];
-$insn_data{xio_bottom_name} = [40, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{xio_bottom_gv} = [41, \&PUT_svindex, "GET_svindex"];
-$insn_data{xio_subprocess} = [42, \&PUT_U16, "GET_U16"];
-$insn_data{xio_type} = [43, \&PUT_U8, "GET_U8"];
-$insn_data{xio_flags} = [44, \&PUT_U8, "GET_U8"];
-$insn_data{xcv_stash} = [45, \&PUT_svindex, "GET_svindex"];
-$insn_data{xcv_start} = [46, \&PUT_opindex, "GET_opindex"];
-$insn_data{xcv_root} = [47, \&PUT_opindex, "GET_opindex"];
-$insn_data{xcv_gv} = [48, \&PUT_svindex, "GET_svindex"];
-$insn_data{xcv_file} = [49, \&PUT_pvindex, "GET_pvindex"];
-$insn_data{xcv_depth} = [50, \&PUT_I32, "GET_I32"];
-$insn_data{xcv_padlist} = [51, \&PUT_svindex, "GET_svindex"];
-$insn_data{xcv_outside} = [52, \&PUT_svindex, "GET_svindex"];
-$insn_data{xcv_flags} = [53, \&PUT_U16, "GET_U16"];
-$insn_data{av_extend} = [54, \&PUT_I32, "GET_I32"];
-$insn_data{av_push} = [55, \&PUT_svindex, "GET_svindex"];
-$insn_data{xav_fill} = [56, \&PUT_I32, "GET_I32"];
-$insn_data{xav_max} = [57, \&PUT_I32, "GET_I32"];
-$insn_data{xav_flags} = [58, \&PUT_U8, "GET_U8"];
-$insn_data{xhv_riter} = [59, \&PUT_I32, "GET_I32"];
-$insn_data{xhv_name} = [60, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{hv_store} = [61, \&PUT_svindex, "GET_svindex"];
-$insn_data{sv_magic} = [62, \&PUT_U8, "GET_U8"];
-$insn_data{mg_obj} = [63, \&PUT_svindex, "GET_svindex"];
-$insn_data{mg_private} = [64, \&PUT_U16, "GET_U16"];
-$insn_data{mg_flags} = [65, \&PUT_U8, "GET_U8"];
-$insn_data{mg_pv} = [66, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{xmg_stash} = [67, \&PUT_svindex, "GET_svindex"];
-$insn_data{gv_fetchpv} = [68, \&PUT_strconst, "GET_strconst"];
-$insn_data{gv_stashpv} = [69, \&PUT_strconst, "GET_strconst"];
-$insn_data{gp_sv} = [70, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_refcnt} = [71, \&PUT_U32, "GET_U32"];
-$insn_data{gp_refcnt_add} = [72, \&PUT_I32, "GET_I32"];
-$insn_data{gp_av} = [73, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_hv} = [74, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_cv} = [75, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_file} = [76, \&PUT_pvindex, "GET_pvindex"];
-$insn_data{gp_io} = [77, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_form} = [78, \&PUT_svindex, "GET_svindex"];
-$insn_data{gp_cvgen} = [79, \&PUT_U32, "GET_U32"];
-$insn_data{gp_line} = [80, \&PUT_U16, "GET_U16"];
-$insn_data{gp_share} = [81, \&PUT_svindex, "GET_svindex"];
-$insn_data{xgv_flags} = [82, \&PUT_U8, "GET_U8"];
-$insn_data{op_next} = [83, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_sibling} = [84, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_ppaddr} = [85, \&PUT_strconst, "GET_strconst"];
-$insn_data{op_targ} = [86, \&PUT_U32, "GET_U32"];
-$insn_data{op_type} = [87, \&PUT_U16, "GET_U16"];
-$insn_data{op_seq} = [88, \&PUT_U16, "GET_U16"];
-$insn_data{op_flags} = [89, \&PUT_U8, "GET_U8"];
-$insn_data{op_private} = [90, \&PUT_U8, "GET_U8"];
-$insn_data{op_first} = [91, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_last} = [92, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_other} = [93, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_pmreplroot} = [94, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_pmreplrootgv} = [95, \&PUT_svindex, "GET_svindex"];
-$insn_data{op_pmreplstart} = [96, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_pmnext} = [97, \&PUT_opindex, "GET_opindex"];
-$insn_data{pregcomp} = [98, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{op_pmflags} = [99, \&PUT_U16, "GET_U16"];
-$insn_data{op_pmpermflags} = [100, \&PUT_U16, "GET_U16"];
-$insn_data{op_sv} = [101, \&PUT_svindex, "GET_svindex"];
-$insn_data{op_padix} = [102, \&PUT_U32, "GET_U32"];
-$insn_data{op_pv} = [103, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{op_pv_tr} = [104, \&PUT_op_tr_array, "GET_op_tr_array"];
-$insn_data{op_redoop} = [105, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_nextop} = [106, \&PUT_opindex, "GET_opindex"];
-$insn_data{op_lastop} = [107, \&PUT_opindex, "GET_opindex"];
-$insn_data{cop_label} = [108, \&PUT_pvindex, "GET_pvindex"];
-$insn_data{cop_stashpv} = [109, \&PUT_pvindex, "GET_pvindex"];
-$insn_data{cop_file} = [110, \&PUT_pvindex, "GET_pvindex"];
-$insn_data{cop_seq} = [111, \&PUT_U32, "GET_U32"];
-$insn_data{cop_arybase} = [112, \&PUT_I32, "GET_I32"];
-$insn_data{cop_line} = [113, \&PUT_U16, "GET_U16"];
-$insn_data{cop_warnings} = [114, \&PUT_svindex, "GET_svindex"];
-$insn_data{main_start} = [115, \&PUT_opindex, "GET_opindex"];
-$insn_data{main_root} = [116, \&PUT_opindex, "GET_opindex"];
-$insn_data{curpad} = [117, \&PUT_svindex, "GET_svindex"];
-$insn_data{push_begin} = [118, \&PUT_svindex, "GET_svindex"];
-$insn_data{push_init} = [119, \&PUT_svindex, "GET_svindex"];
-$insn_data{push_end} = [120, \&PUT_svindex, "GET_svindex"];
-
-my ($insn_name, $insn_data);
-while (($insn_name, $insn_data) = each %insn_data) {
- $insn_name[$insn_data->[0]] = $insn_name;
-}
-# Fill in any gaps
-@insn_name = map($_ || "unused", @insn_name);
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Asmdata - Autogenerated data about Perl ops, used to generate bytecode
-
-=head1 SYNOPSIS
-
- use Asmdata;
-
-=head1 DESCRIPTION
-
-See F<ext/B/B/Asmdata.pm>.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Assembler.pm b/contrib/perl5/ext/B/B/Assembler.pm
deleted file mode 100644
index 5e798ce..0000000
--- a/contrib/perl5/ext/B/B/Assembler.pm
+++ /dev/null
@@ -1,285 +0,0 @@
-# Assembler.pm
-#
-# Copyright (c) 1996 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::Assembler;
-use Exporter;
-use B qw(ppname);
-use B::Asmdata qw(%insn_data @insn_name);
-use Config qw(%Config);
-require ByteLoader; # we just need its $VERSIOM
-
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(assemble_fh newasm endasm assemble);
-$VERSION = 0.02;
-
-use strict;
-my %opnumber;
-my ($i, $opname);
-for ($i = 0; defined($opname = ppname($i)); $i++) {
- $opnumber{$opname} = $i;
-}
-
-my($linenum, $errors, $out); # global state, set up by newasm
-
-sub error {
- my $str = shift;
- warn "$linenum: $str\n";
- $errors++;
-}
-
-my $debug = 0;
-sub debug { $debug = shift }
-
-#
-# First define all the data conversion subs to which Asmdata will refer
-#
-
-sub B::Asmdata::PUT_U8 {
- my $arg = shift;
- my $c = uncstring($arg);
- if (defined($c)) {
- if (length($c) != 1) {
- error "argument for U8 is too long: $c";
- $c = substr($c, 0, 1);
- }
- } else {
- $c = chr($arg);
- }
- return $c;
-}
-
-sub B::Asmdata::PUT_U16 { pack("S", $_[0]) }
-sub B::Asmdata::PUT_U32 { pack("L", $_[0]) }
-sub B::Asmdata::PUT_I32 { pack("L", $_[0]) }
-sub B::Asmdata::PUT_NV { sprintf("%s\0", $_[0]) } # "%lf" looses precision and pack('d',...)
- # may not even be portable between compilers
-sub B::Asmdata::PUT_objindex { pack("L", $_[0]) } # could allow names here
-sub B::Asmdata::PUT_svindex { &B::Asmdata::PUT_objindex }
-sub B::Asmdata::PUT_opindex { &B::Asmdata::PUT_objindex }
-sub B::Asmdata::PUT_pvindex { &B::Asmdata::PUT_objindex }
-
-sub B::Asmdata::PUT_strconst {
- my $arg = shift;
- $arg = uncstring($arg);
- if (!defined($arg)) {
- error "bad string constant: $arg";
- return "";
- }
- if ($arg =~ s/\0//g) {
- error "string constant argument contains NUL: $arg";
- }
- return $arg . "\0";
-}
-
-sub B::Asmdata::PUT_pvcontents {
- my $arg = shift;
- error "extraneous argument: $arg" if defined $arg;
- return "";
-}
-sub B::Asmdata::PUT_PV {
- my $arg = shift;
- $arg = uncstring($arg);
- error "bad string argument: $arg" unless defined($arg);
- return pack("L", length($arg)) . $arg;
-}
-sub B::Asmdata::PUT_comment_t {
- my $arg = shift;
- $arg = uncstring($arg);
- error "bad string argument: $arg" unless defined($arg);
- if ($arg =~ s/\n//g) {
- error "comment argument contains linefeed: $arg";
- }
- return $arg . "\n";
-}
-sub B::Asmdata::PUT_double { sprintf("%s\0", $_[0]) } # see PUT_NV above
-sub B::Asmdata::PUT_none {
- my $arg = shift;
- error "extraneous argument: $arg" if defined $arg;
- return "";
-}
-sub B::Asmdata::PUT_op_tr_array {
- my $arg = shift;
- my @ary = split(/\s*,\s*/, $arg);
- if (@ary != 256) {
- error "wrong number of arguments to op_tr_array";
- @ary = (0) x 256;
- }
- return pack("S256", @ary);
-}
-# XXX Check this works
-sub B::Asmdata::PUT_IV64 {
- my $arg = shift;
- return pack("LL", $arg >> 32, $arg & 0xffffffff);
-}
-
-my %unesc = (n => "\n", r => "\r", t => "\t", a => "\a",
- b => "\b", f => "\f", v => "\013");
-
-sub uncstring {
- my $s = shift;
- $s =~ s/^"// and $s =~ s/"$// or return undef;
- $s =~ s/\\(\d\d\d|.)/length($1) == 3 ? chr(oct($1)) : ($unesc{$1}||$1)/eg;
- return $s;
-}
-
-sub strip_comments {
- my $stmt = shift;
- # Comments only allowed in instructions which don't take string arguments
- $stmt =~ s{
- (?sx) # Snazzy extended regexp coming up. Also, treat
- # string as a single line so .* eats \n characters.
- ^\s* # Ignore leading whitespace
- (
- [^"]* # A double quote '"' indicates a string argument. If we
- # find a double quote, the match fails and we strip nothing.
- )
- \s*\# # Any amount of whitespace plus the comment marker...
- .*$ # ...which carries on to end-of-string.
- }{$1}; # Keep only the instruction and optional argument.
- return $stmt;
-}
-
-# create the ByteCode header: magic, archname, ByteLoader $VERSION, ivsize,
-# ptrsize, byteorder
-# nvtype is irrelevant (floats are stored as strings)
-# byteorder is strconst not U32 because of varying size issues
-
-sub gen_header {
- my $header = "";
-
- $header .= B::Asmdata::PUT_U32(0x43424c50); # 'PLBC'
- $header .= B::Asmdata::PUT_strconst('"' . $Config{archname}. '"');
- $header .= B::Asmdata::PUT_strconst(qq["$ByteLoader::VERSION"]);
- $header .= B::Asmdata::PUT_U32($Config{ivsize});
- $header .= B::Asmdata::PUT_U32($Config{ptrsize});
- $header .= B::Asmdata::PUT_strconst(sprintf(qq["0x%s"], $Config{byteorder}));
-
- $header;
-}
-
-sub parse_statement {
- my $stmt = shift;
- my ($insn, $arg) = $stmt =~ m{
- (?sx)
- ^\s* # allow (but ignore) leading whitespace
- (.*?) # Instruction continues up until...
- (?: # ...an optional whitespace+argument group
- \s+ # first whitespace.
- (.*) # The argument is all the rest (newlines included).
- )?$ # anchor at end-of-line
- };
- if (defined($arg)) {
- if ($arg =~ s/^0x(?=[0-9a-fA-F]+$)//) {
- $arg = hex($arg);
- } elsif ($arg =~ s/^0(?=[0-7]+$)//) {
- $arg = oct($arg);
- } elsif ($arg =~ /^pp_/) {
- $arg =~ s/\s*$//; # strip trailing whitespace
- my $opnum = $opnumber{$arg};
- if (defined($opnum)) {
- $arg = $opnum;
- } else {
- error qq(No such op type "$arg");
- $arg = 0;
- }
- }
- }
- return ($insn, $arg);
-}
-
-sub assemble_insn {
- my ($insn, $arg) = @_;
- my $data = $insn_data{$insn};
- if (defined($data)) {
- my ($bytecode, $putsub) = @{$data}[0, 1];
- my $argcode = &$putsub($arg);
- return chr($bytecode).$argcode;
- } else {
- error qq(no such instruction "$insn");
- return "";
- }
-}
-
-sub assemble_fh {
- my ($fh, $out) = @_;
- my $line;
- my $asm = newasm($out);
- while ($line = <$fh>) {
- assemble($line);
- }
- endasm();
-}
-
-sub newasm {
- my($outsub) = @_;
-
- die "Invalid printing routine for B::Assembler\n" unless ref $outsub eq 'CODE';
- die <<EOD if ref $out;
-Can't have multiple byteassembly sessions at once!
- (perhaps you forgot an endasm()?)
-EOD
-
- $linenum = $errors = 0;
- $out = $outsub;
-
- $out->(gen_header());
-}
-
-sub endasm {
- if ($errors) {
- die "There were $errors assembly errors\n";
- }
- $linenum = $errors = $out = 0;
-}
-
-sub assemble {
- my($line) = @_;
- my ($insn, $arg);
- $linenum++;
- chomp $line;
- if ($debug) {
- my $quotedline = $line;
- $quotedline =~ s/\\/\\\\/g;
- $quotedline =~ s/"/\\"/g;
- $out->(assemble_insn("comment", qq("$quotedline")));
- }
- $line = strip_comments($line) or next;
- ($insn, $arg) = parse_statement($line);
- $out->(assemble_insn($insn, $arg));
- if ($debug) {
- $out->(assemble_insn("nop", undef));
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Assembler - Assemble Perl bytecode
-
-=head1 SYNOPSIS
-
- use B::Assembler qw(newasm endasm assemble);
- newasm(\&printsub); # sets up for assembly
- assemble($buf); # assembles one line
- endasm(); # closes down
-
- use B::Assembler qw(assemble_fh);
- assemble_fh($fh, \&printsub); # assemble everything in $fh
-
-=head1 DESCRIPTION
-
-See F<ext/B/B/Assembler.pm>.
-
-=head1 AUTHORS
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-Per-statement interface by Benjamin Stuhl, C<sho_pi@hotmail.com>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Bblock.pm b/contrib/perl5/ext/B/B/Bblock.pm
deleted file mode 100644
index fe7fc52..0000000
--- a/contrib/perl5/ext/B/B/Bblock.pm
+++ /dev/null
@@ -1,180 +0,0 @@
-package B::Bblock;
-use Exporter ();
-@ISA = "Exporter";
-@EXPORT_OK = qw(find_leaders);
-
-use B qw(peekop walkoptree walkoptree_exec
- main_root main_start svref_2object
- OPf_SPECIAL OPf_STACKED );
-
-use B::Terse;
-use strict;
-
-my $bblock;
-my @bblock_ends;
-
-sub mark_leader {
- my $op = shift;
- if ($$op) {
- $bblock->{$$op} = $op;
- }
-}
-
-sub remove_sortblock{
- foreach (keys %$bblock){
- my $leader=$$bblock{$_};
- delete $$bblock{$_} if( $leader == 0);
- }
-}
-sub find_leaders {
- my ($root, $start) = @_;
- $bblock = {};
- mark_leader($start) if ( ref $start ne "B::NULL" );
- walkoptree($root, "mark_if_leader") if ((ref $root) ne "B::NULL") ;
- remove_sortblock();
- return $bblock;
-}
-
-# Debugging
-sub walk_bblocks {
- my ($root, $start) = @_;
- my ($op, $lastop, $leader, $bb);
- $bblock = {};
- mark_leader($start);
- walkoptree($root, "mark_if_leader");
- my @leaders = values %$bblock;
- while ($leader = shift @leaders) {
- $lastop = $leader;
- $op = $leader->next;
- while ($$op && !exists($bblock->{$$op})) {
- $bblock->{$$op} = $leader;
- $lastop = $op;
- $op = $op->next;
- }
- push(@bblock_ends, [$leader, $lastop]);
- }
- foreach $bb (@bblock_ends) {
- ($leader, $lastop) = @$bb;
- printf "%s .. %s\n", peekop($leader), peekop($lastop);
- for ($op = $leader; $$op != $$lastop; $op = $op->next) {
- printf " %s\n", peekop($op);
- }
- printf " %s\n", peekop($lastop);
- }
- print "-------\n";
- walkoptree_exec($start, "terse");
-}
-
-sub walk_bblocks_obj {
- my $cvref = shift;
- my $cv = svref_2object($cvref);
- walk_bblocks($cv->ROOT, $cv->START);
-}
-
-sub B::OP::mark_if_leader {}
-
-sub B::COP::mark_if_leader {
- my $op = shift;
- if ($op->label) {
- mark_leader($op);
- }
-}
-
-sub B::LOOP::mark_if_leader {
- my $op = shift;
- mark_leader($op->next);
- mark_leader($op->nextop);
- mark_leader($op->redoop);
- mark_leader($op->lastop->next);
-}
-
-sub B::LOGOP::mark_if_leader {
- my $op = shift;
- my $opname = $op->name;
- mark_leader($op->next);
- if ($opname eq "entertry") {
- mark_leader($op->other->next);
- } else {
- mark_leader($op->other);
- }
-}
-
-sub B::LISTOP::mark_if_leader {
- my $op = shift;
- my $first=$op->first;
- $first=$first->next while ($first->name eq "null");
- mark_leader($op->first) unless (exists( $bblock->{$$first}));
- mark_leader($op->next);
- if ($op->name eq "sort" and $op->flags & OPf_SPECIAL
- and $op->flags & OPf_STACKED){
- my $root=$op->first->sibling->first;
- my $leader=$root->first;
- $bblock->{$$leader} = 0;
- }
-}
-
-sub B::PMOP::mark_if_leader {
- my $op = shift;
- if ($op->name ne "pushre") {
- my $replroot = $op->pmreplroot;
- if ($$replroot) {
- mark_leader($replroot);
- mark_leader($op->next);
- mark_leader($op->pmreplstart);
- }
- }
-}
-
-# PMOP stuff omitted
-
-sub compile {
- my @options = @_;
- B::clearsym();
- if (@options) {
- return sub {
- my $objname;
- foreach $objname (@options) {
- $objname = "main::$objname" unless $objname =~ /::/;
- eval "walk_bblocks_obj(\\&$objname)";
- die "walk_bblocks_obj(\\&$objname) failed: $@" if $@;
- }
- }
- } else {
- return sub { walk_bblocks(main_root, main_start) };
- }
-}
-
-# Basic block leaders:
-# Any COP (pp_nextstate) with a non-NULL label
-# [The op after a pp_enter] Omit
-# [The op after a pp_entersub. Don't count this one.]
-# The ops pointed at by nextop, redoop and lastop->op_next of a LOOP
-# The ops pointed at by op_next and op_other of a LOGOP, except
-# for pp_entertry which has op_next and op_other->op_next
-# The op pointed at by op_pmreplstart of a PMOP
-# The op pointed at by op_other->op_pmreplstart of pp_substcont?
-# [The op after a pp_return] Omit
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Bblock - Walk basic blocks
-
-=head1 SYNOPSIS
-
- perl -MO=Bblock[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This module is used by the B::CC back end. It walks "basic blocks".
-A basic block is a series of operations which is known to execute from
-start to finish, with no possiblity of branching or halting.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Bytecode.pm b/contrib/perl5/ext/B/B/Bytecode.pm
deleted file mode 100644
index 54d7c53..0000000
--- a/contrib/perl5/ext/B/B/Bytecode.pm
+++ /dev/null
@@ -1,998 +0,0 @@
-# Bytecode.pm
-#
-# Copyright (c) 1996-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::Bytecode;
-
-use strict;
-use Carp;
-use B qw(main_cv main_root main_start comppadlist
- class peekop walkoptree svref_2object cstring walksymtable
- init_av begin_av end_av
- SVf_POK SVp_POK SVf_IOK SVp_IOK SVf_NOK SVp_NOK
- SVf_READONLY GVf_IMPORTED_AV GVf_IMPORTED_CV GVf_IMPORTED_HV
- GVf_IMPORTED_SV SVTYPEMASK
- );
-use B::Asmdata qw(@optype @specialsv_name);
-use B::Assembler qw(newasm endasm assemble);
-
-my %optype_enum;
-my $i;
-for ($i = 0; $i < @optype; $i++) {
- $optype_enum{$optype[$i]} = $i;
-}
-
-# Following is SVf_POK|SVp_POK
-# XXX Shouldn't be hardwired
-sub POK () { SVf_POK|SVp_POK }
-
-# Following is SVf_IOK|SVp_IOK
-# XXX Shouldn't be hardwired
-sub IOK () { SVf_IOK|SVp_IOK }
-
-# Following is SVf_NOK|SVp_NOK
-# XXX Shouldn't be hardwired
-sub NOK () { SVf_NOK|SVp_NOK }
-
-# nonexistant flags (see B::GV::bytecode for usage)
-sub GVf_IMPORTED_IO () { 0; }
-sub GVf_IMPORTED_FORM () { 0; }
-
-my ($verbose, $no_assemble, $debug_bc, $debug_cv);
-my @packages; # list of packages to compile
-
-sub asm (@) { # print replacement that knows about assembling
- if ($no_assemble) {
- print @_;
- } else {
- my $buf = join '', @_;
- assemble($_) for (split /\n/, $buf);
- }
-}
-
-sub asmf (@) { # printf replacement that knows about assembling
- if ($no_assemble) {
- printf shift(), @_;
- } else {
- my $format = shift;
- my $buf = sprintf $format, @_;
- assemble($_) for (split /\n/, $buf);
- }
-}
-
-# Optimisation options. On the command line, use hyphens instead of
-# underscores for compatibility with gcc-style options. We use
-# underscores here because they are OK in (strict) barewords.
-my ($compress_nullops, $omit_seq, $bypass_nullops);
-my %optimise = (compress_nullops => \$compress_nullops,
- omit_sequence_numbers => \$omit_seq,
- bypass_nullops => \$bypass_nullops);
-
-my $strip_syntree; # this is left here in case stripping the
- # syntree ever becomes safe again
- # -- BKS, June 2000
-
-my $nextix = 0;
-my %symtable; # maps object addresses to object indices.
- # Filled in at allocation (newsv/newop) time.
-
-my %saved; # maps object addresses (for SVish classes) to "saved yet?"
- # flag. Set at FOO::bytecode time usually by SV::bytecode.
- # Manipulated via saved(), mark_saved(), unmark_saved().
-
-my %strtable; # maps shared strings to object indices
- # Filled in at allocation (pvix) time
-
-my $svix = -1; # we keep track of when the sv register contains an element
- # of the object table to avoid unnecessary repeated
- # consecutive ldsv instructions.
-
-my $opix = -1; # Ditto for the op register.
-
-sub ldsv {
- my $ix = shift;
- if ($ix != $svix) {
- asm "ldsv $ix\n";
- $svix = $ix;
- }
-}
-
-sub stsv {
- my $ix = shift;
- asm "stsv $ix\n";
- $svix = $ix;
-}
-
-sub set_svix {
- $svix = shift;
-}
-
-sub ldop {
- my $ix = shift;
- if ($ix != $opix) {
- asm "ldop $ix\n";
- $opix = $ix;
- }
-}
-
-sub stop {
- my $ix = shift;
- asm "stop $ix\n";
- $opix = $ix;
-}
-
-sub set_opix {
- $opix = shift;
-}
-
-sub pvstring {
- my $str = shift;
- if (defined($str)) {
- return cstring($str . "\0");
- } else {
- return '""';
- }
-}
-
-sub nv {
- # print full precision
- my $str = sprintf "%.40f", $_[0];
- $str =~ s/0+$//; # remove trailing zeros
- $str =~ s/\.$/.0/;
- return $str;
-}
-
-sub saved { $saved{${$_[0]}} }
-sub mark_saved { $saved{${$_[0]}} = 1 }
-sub unmark_saved { $saved{${$_[0]}} = 0 }
-
-sub debug { $debug_bc = shift }
-
-sub pvix { # save a shared PV (mainly for COPs)
- return $strtable{$_[0]} if defined($strtable{$_[0]});
- asmf "newpv %s\n", pvstring($_[0]);
- my $ix = $nextix++;
- $strtable{$_[0]} = $ix;
- asmf "stpv %d\n", $ix;
- return $ix;
-}
-
-sub B::OBJECT::nyi {
- my $obj = shift;
- warn sprintf("bytecode save method for %s (0x%x) not yet implemented\n",
- class($obj), $$obj);
-}
-
-#
-# objix may stomp on the op register (for op objects)
-# or the sv register (for SV objects)
-#
-sub B::OBJECT::objix {
- my $obj = shift;
- my $ix = $symtable{$$obj};
- if (defined($ix)) {
- return $ix;
- } else {
- $obj->newix($nextix);
- return $symtable{$$obj} = $nextix++;
- }
-}
-
-sub B::SV::newix {
- my ($sv, $ix) = @_;
- asmf "newsv %d\t# %s\n", $sv->FLAGS & SVTYPEMASK, class($sv);
- stsv($ix);
-}
-
-sub B::GV::newix {
- my ($gv, $ix) = @_;
- my $gvname = $gv->NAME;
- my $name = cstring($gv->STASH->NAME . "::" . $gvname);
- asm "gv_fetchpv $name\n";
- stsv($ix);
-}
-
-sub B::HV::newix {
- my ($hv, $ix) = @_;
- my $name = $hv->NAME;
- if ($name) {
- # It's a stash
- asmf "gv_stashpv %s\n", cstring($name);
- stsv($ix);
- } else {
- # It's an ordinary HV. Fall back to ordinary newix method
- $hv->B::SV::newix($ix);
- }
-}
-
-sub B::SPECIAL::newix {
- my ($sv, $ix) = @_;
- # Special case. $$sv is not the address of the SV but an
- # index into svspecialsv_list.
- asmf "ldspecsv $$sv\t# %s\n", $specialsv_name[$$sv];
- stsv($ix);
-}
-
-sub B::OP::newix {
- my ($op, $ix) = @_;
- my $class = class($op);
- my $typenum = $optype_enum{$class};
- croak("OP::newix: can't understand class $class") unless defined($typenum);
- asm "newop $typenum\t# $class\n";
- stop($ix);
-}
-
-sub B::OP::walkoptree_debug {
- my $op = shift;
- warn(sprintf("walkoptree: %s\n", peekop($op)));
-}
-
-sub B::OP::bytecode {
- my $op = shift;
- my $next = $op->next;
- my $nextix;
- my $sibix = $op->sibling->objix unless $strip_syntree;
- my $ix = $op->objix;
- my $type = $op->type;
-
- if ($bypass_nullops) {
- $next = $next->next while $$next && $next->type == 0;
- }
- $nextix = $next->objix;
-
- asmf "# %s\n", peekop($op) if $debug_bc;
- ldop($ix);
- asm "op_next $nextix\n";
- asm "op_sibling $sibix\n" unless $strip_syntree;
- asmf "op_type %s\t# %d\n", "pp_" . $op->name, $type;
- asmf("op_seq %d\n", $op->seq) unless $omit_seq;
- if ($type || !$compress_nullops) {
- asmf "op_targ %d\nop_flags 0x%x\nop_private 0x%x\n",
- $op->targ, $op->flags, $op->private;
- }
-}
-
-sub B::UNOP::bytecode {
- my $op = shift;
- my $firstix = $op->first->objix unless $strip_syntree;
- $op->B::OP::bytecode;
- if (($op->type || !$compress_nullops) && !$strip_syntree) {
- asm "op_first $firstix\n";
- }
-}
-
-sub B::LOGOP::bytecode {
- my $op = shift;
- my $otherix = $op->other->objix;
- $op->B::UNOP::bytecode;
- asm "op_other $otherix\n";
-}
-
-sub B::SVOP::bytecode {
- my $op = shift;
- my $sv = $op->sv;
- my $svix = $sv->objix;
- $op->B::OP::bytecode;
- asm "op_sv $svix\n";
- $sv->bytecode;
-}
-
-sub B::PADOP::bytecode {
- my $op = shift;
- my $padix = $op->padix;
- $op->B::OP::bytecode;
- asm "op_padix $padix\n";
-}
-
-sub B::PVOP::bytecode {
- my $op = shift;
- my $pv = $op->pv;
- $op->B::OP::bytecode;
- #
- # This would be easy except that OP_TRANS uses a PVOP to store an
- # endian-dependent array of 256 shorts instead of a plain string.
- #
- if ($op->name eq "trans") {
- my @shorts = unpack("s256", $pv); # assembler handles endianness
- asm "op_pv_tr ", join(",", @shorts), "\n";
- } else {
- asmf "newpv %s\nop_pv\n", pvstring($pv);
- }
-}
-
-sub B::BINOP::bytecode {
- my $op = shift;
- my $lastix = $op->last->objix unless $strip_syntree;
- $op->B::UNOP::bytecode;
- if (($op->type || !$compress_nullops) && !$strip_syntree) {
- asm "op_last $lastix\n";
- }
-}
-
-sub B::LOOP::bytecode {
- my $op = shift;
- my $redoopix = $op->redoop->objix;
- my $nextopix = $op->nextop->objix;
- my $lastopix = $op->lastop->objix;
- $op->B::LISTOP::bytecode;
- asm "op_redoop $redoopix\nop_nextop $nextopix\nop_lastop $lastopix\n";
-}
-
-sub B::COP::bytecode {
- my $op = shift;
- my $file = $op->file;
- my $line = $op->line;
- if ($debug_bc) { # do this early to aid debugging
- asmf "# line %s:%d\n", $file, $line;
- }
- my $stashpv = $op->stashpv;
- my $warnings = $op->warnings;
- my $warningsix = $warnings->objix;
- my $labelix = pvix($op->label);
- my $stashix = pvix($stashpv);
- my $fileix = pvix($file);
- $warnings->bytecode;
- $op->B::OP::bytecode;
- asmf <<"EOT", $labelix, $stashix, $op->cop_seq, $fileix, $op->arybase;
-cop_label %d
-cop_stashpv %d
-cop_seq %d
-cop_file %d
-cop_arybase %d
-cop_line $line
-cop_warnings $warningsix
-EOT
-}
-
-sub B::PMOP::bytecode {
- my $op = shift;
- my $replroot = $op->pmreplroot;
- my $replrootix = $replroot->objix;
- my $replstartix = $op->pmreplstart->objix;
- my $opname = $op->name;
- # pmnext is corrupt in some PMOPs (see misc.t for example)
- #my $pmnextix = $op->pmnext->objix;
-
- if ($$replroot) {
- # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
- # argument to a split) stores a GV in op_pmreplroot instead
- # of a substitution syntax tree. We don't want to walk that...
- if ($opname eq "pushre") {
- $replroot->bytecode;
- } else {
- walkoptree($replroot, "bytecode");
- }
- }
- $op->B::LISTOP::bytecode;
- if ($opname eq "pushre") {
- asmf "op_pmreplrootgv $replrootix\n";
- } else {
- asm "op_pmreplroot $replrootix\nop_pmreplstart $replstartix\n";
- }
- my $re = pvstring($op->precomp);
- # op_pmnext omitted since a perl bug means it's sometime corrupt
- asmf <<"EOT", $op->pmflags, $op->pmpermflags;
-op_pmflags 0x%x
-op_pmpermflags 0x%x
-newpv $re
-pregcomp
-EOT
-}
-
-sub B::SV::bytecode {
- my $sv = shift;
- return if saved($sv);
- my $ix = $sv->objix;
- my $refcnt = $sv->REFCNT;
- my $flags = sprintf("0x%x", $sv->FLAGS);
- ldsv($ix);
- asm "sv_refcnt $refcnt\nsv_flags $flags\n";
- mark_saved($sv);
-}
-
-sub B::PV::bytecode {
- my $sv = shift;
- return if saved($sv);
- $sv->B::SV::bytecode;
- asmf("newpv %s\nxpv\n", pvstring($sv->PV)) if $sv->FLAGS & POK;
-}
-
-sub B::IV::bytecode {
- my $sv = shift;
- return if saved($sv);
- my $iv = $sv->IVX;
- $sv->B::SV::bytecode;
- asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32" if $sv->FLAGS & IOK; # could be PVNV
-}
-
-sub B::NV::bytecode {
- my $sv = shift;
- return if saved($sv);
- $sv->B::SV::bytecode;
- asmf "xnv %s\n", nv($sv->NVX);
-}
-
-sub B::RV::bytecode {
- my $sv = shift;
- return if saved($sv);
- my $rv = $sv->RV;
- my $rvix = $rv->objix;
- $rv->bytecode;
- $sv->B::SV::bytecode;
- asm "xrv $rvix\n";
-}
-
-sub B::PVIV::bytecode {
- my $sv = shift;
- return if saved($sv);
- my $iv = $sv->IVX;
- $sv->B::PV::bytecode;
- asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32";
-}
-
-sub B::PVNV::bytecode {
- my $sv = shift;
- my $flag = shift || 0;
- # The $flag argument is passed through PVMG::bytecode by BM::bytecode
- # and AV::bytecode and indicates special handling. $flag = 1 is used by
- # BM::bytecode and means that we should ensure we save the whole B-M
- # table. It consists of 257 bytes (256 char array plus a final \0)
- # which follow the ordinary PV+\0 and the 257 bytes are *not* reflected
- # in SvCUR. $flag = 2 is used by AV::bytecode and means that we only
- # call SV::bytecode instead of saving PV and calling NV::bytecode since
- # PV/NV/IV stuff is different for AVs.
- return if saved($sv);
- if ($flag == 2) {
- $sv->B::SV::bytecode;
- } else {
- my $pv = $sv->PV;
- $sv->B::IV::bytecode;
- asmf "xnv %s\n", nv($sv->NVX);
- if ($flag == 1) {
- $pv .= "\0" . $sv->TABLE;
- asmf "newpv %s\npv_cur %d\nxpv\n", pvstring($pv),length($pv)-257;
- } else {
- asmf("newpv %s\nxpv\n", pvstring($pv)) if $sv->FLAGS & POK;
- }
- }
-}
-
-sub B::PVMG::bytecode {
- my ($sv, $flag) = @_;
- # See B::PVNV::bytecode for an explanation of $flag.
- return if saved($sv);
- # XXX We assume SvSTASH is already saved and don't save it later ourselves
- my $stashix = $sv->SvSTASH->objix;
- my @mgchain = $sv->MAGIC;
- my (@mgobjix, $mg);
- #
- # We need to traverse the magic chain and get objix for each OBJ
- # field *before* we do B::PVNV::bytecode since objix overwrites
- # the sv register. However, we need to write the magic-saving
- # bytecode *after* B::PVNV::bytecode since sv isn't initialised
- # to refer to $sv until then.
- #
- @mgobjix = map($_->OBJ->objix, @mgchain);
- $sv->B::PVNV::bytecode($flag);
- asm "xmg_stash $stashix\n";
- foreach $mg (@mgchain) {
- asmf "sv_magic %s\nmg_obj %d\nnewpv %s\nmg_pv\n",
- cstring($mg->TYPE), shift(@mgobjix), pvstring($mg->PTR);
- }
-}
-
-sub B::PVLV::bytecode {
- my $sv = shift;
- return if saved($sv);
- $sv->B::PVMG::bytecode;
- asmf <<'EOT', $sv->TARGOFF, $sv->TARGLEN, cstring($sv->TYPE);
-xlv_targoff %d
-xlv_targlen %d
-xlv_type %s
-EOT
-}
-
-sub B::BM::bytecode {
- my $sv = shift;
- return if saved($sv);
- # See PVNV::bytecode for an explanation of what the argument does
- $sv->B::PVMG::bytecode(1);
- asmf "xbm_useful %d\nxbm_previous %d\nxbm_rare %d\n",
- $sv->USEFUL, $sv->PREVIOUS, $sv->RARE;
-}
-
-sub empty_gv { # is a GV empty except for imported stuff?
- my $gv = shift;
-
- return 0 if ($gv->SV->FLAGS & SVTYPEMASK); # sv not SVt_NULL
- my @subfield_names = qw(AV HV CV FORM IO);
- @subfield_names = grep {;
- no strict 'refs';
- !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->()) && ${$gv->$_()};
- } @subfield_names;
- return scalar @subfield_names;
-}
-
-sub B::GV::bytecode {
- my $gv = shift;
- return if saved($gv);
- return unless grep { $_ eq $gv->STASH->NAME; } @packages;
- return if $gv->NAME =~ m/^\(/; # ignore overloads - they'll be rebuilt
- my $ix = $gv->objix;
- mark_saved($gv);
- ldsv($ix);
- asmf <<"EOT", $gv->FLAGS, $gv->GvFLAGS;
-sv_flags 0x%x
-xgv_flags 0x%x
-EOT
- my $refcnt = $gv->REFCNT;
- asmf("sv_refcnt_add %d\n", $refcnt - 1) if $refcnt > 1;
- return if $gv->is_empty;
- asmf <<"EOT", $gv->LINE, pvix($gv->FILE);
-gp_line %d
-gp_file %d
-EOT
- my $gvname = $gv->NAME;
- my $name = cstring($gv->STASH->NAME . "::" . $gvname);
- my $egv = $gv->EGV;
- my $egvix = $egv->objix;
- my $gvrefcnt = $gv->GvREFCNT;
- asmf("gp_refcnt_add %d\n", $gvrefcnt - 1) if $gvrefcnt > 1;
- if ($gvrefcnt > 1 && $ix != $egvix) {
- asm "gp_share $egvix\n";
- } else {
- if ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) {
- my $i;
- my @subfield_names = qw(SV AV HV CV FORM IO);
- @subfield_names = grep {;
- no strict 'refs';
- !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->());
- } @subfield_names;
- my @subfields = map($gv->$_(), @subfield_names);
- my @ixes = map($_->objix, @subfields);
- # Reset sv register for $gv
- ldsv($ix);
- for ($i = 0; $i < @ixes; $i++) {
- asmf "gp_%s %d\n", lc($subfield_names[$i]), $ixes[$i];
- }
- # Now save all the subfields
- my $sv;
- foreach $sv (@subfields) {
- $sv->bytecode;
- }
- }
- }
-}
-
-sub B::HV::bytecode {
- my $hv = shift;
- return if saved($hv);
- mark_saved($hv);
- my $name = $hv->NAME;
- my $ix = $hv->objix;
- if (!$name) {
- # It's an ordinary HV. Stashes have NAME set and need no further
- # saving beyond the gv_stashpv that $hv->objix already ensures.
- my @contents = $hv->ARRAY;
- my ($i, @ixes);
- for ($i = 1; $i < @contents; $i += 2) {
- push(@ixes, $contents[$i]->objix);
- }
- for ($i = 1; $i < @contents; $i += 2) {
- $contents[$i]->bytecode;
- }
- ldsv($ix);
- for ($i = 0; $i < @contents; $i += 2) {
- asmf("newpv %s\nhv_store %d\n",
- pvstring($contents[$i]), $ixes[$i / 2]);
- }
- asmf "sv_refcnt %d\nsv_flags 0x%x\n", $hv->REFCNT, $hv->FLAGS;
- }
-}
-
-sub B::AV::bytecode {
- my $av = shift;
- return if saved($av);
- my $ix = $av->objix;
- my $fill = $av->FILL;
- my $max = $av->MAX;
- my (@array, @ixes);
- if ($fill > -1) {
- @array = $av->ARRAY;
- @ixes = map($_->objix, @array);
- my $sv;
- foreach $sv (@array) {
- $sv->bytecode;
- }
- }
- # See PVNV::bytecode for the meaning of the flag argument of 2.
- $av->B::PVMG::bytecode(2);
- # Recover sv register and set AvMAX and AvFILL to -1 (since we
- # create an AV with NEWSV and SvUPGRADE rather than doing newAV
- # which is what sets AvMAX and AvFILL.
- ldsv($ix);
- asmf "sv_flags 0x%x\n", $av->FLAGS & ~SVf_READONLY; # SvREADONLY_off($av) in case PADCONST
- asmf "xav_flags 0x%x\nxav_max -1\nxav_fill -1\n", $av->AvFLAGS;
- if ($fill > -1) {
- my $elix;
- foreach $elix (@ixes) {
- asm "av_push $elix\n";
- }
- } else {
- if ($max > -1) {
- asm "av_extend $max\n";
- }
- }
- asmf "sv_flags 0x%x\n", $av->FLAGS; # restore flags from above
-}
-
-sub B::CV::bytecode {
- my $cv = shift;
- return if saved($cv);
- return if ${$cv->GV} && ($cv->GV->GvFLAGS & GVf_IMPORTED_CV);
- my $fileix = pvix($cv->FILE);
- my $ix = $cv->objix;
- $cv->B::PVMG::bytecode;
- my $i;
- my @subfield_names = qw(ROOT START STASH GV PADLIST OUTSIDE);
- my @subfields = map($cv->$_(), @subfield_names);
- my @ixes = map($_->objix, @subfields);
- # Save OP tree from CvROOT (first element of @subfields)
- my $root = shift @subfields;
- if ($$root) {
- walkoptree($root, "bytecode");
- }
- # Reset sv register for $cv (since above ->objix calls stomped on it)
- ldsv($ix);
- for ($i = 0; $i < @ixes; $i++) {
- asmf "xcv_%s %d\n", lc($subfield_names[$i]), $ixes[$i];
- }
- asmf "xcv_depth %d\nxcv_flags 0x%x\n", $cv->DEPTH, $cv->CvFLAGS;
- asmf "xcv_file %d\n", $fileix;
- # Now save all the subfields (except for CvROOT which was handled
- # above) and CvSTART (now the initial element of @subfields).
- shift @subfields; # bye-bye CvSTART
- my $sv;
- foreach $sv (@subfields) {
- $sv->bytecode;
- }
-}
-
-sub B::IO::bytecode {
- my $io = shift;
- return if saved($io);
- my $ix = $io->objix;
- my $top_gv = $io->TOP_GV;
- my $top_gvix = $top_gv->objix;
- my $fmt_gv = $io->FMT_GV;
- my $fmt_gvix = $fmt_gv->objix;
- my $bottom_gv = $io->BOTTOM_GV;
- my $bottom_gvix = $bottom_gv->objix;
-
- $io->B::PVMG::bytecode;
- ldsv($ix);
- asm "xio_top_gv $top_gvix\n";
- asm "xio_fmt_gv $fmt_gvix\n";
- asm "xio_bottom_gv $bottom_gvix\n";
- my $field;
- foreach $field (qw(TOP_NAME FMT_NAME BOTTOM_NAME)) {
- asmf "newpv %s\nxio_%s\n", pvstring($io->$field()), lc($field);
- }
- foreach $field (qw(LINES PAGE PAGE_LEN LINES_LEFT SUBPROCESS)) {
- asmf "xio_%s %d\n", lc($field), $io->$field();
- }
- asmf "xio_type %s\nxio_flags 0x%x\n", cstring($io->IoTYPE), $io->IoFLAGS;
- $top_gv->bytecode;
- $fmt_gv->bytecode;
- $bottom_gv->bytecode;
-}
-
-sub B::SPECIAL::bytecode {
- # nothing extra needs doing
-}
-
-sub bytecompile_object {
- for my $sv (@_) {
- svref_2object($sv)->bytecode;
- }
-}
-
-sub B::GV::bytecodecv {
- my $gv = shift;
- my $cv = $gv->CV;
- if ($$cv && !saved($cv) && !($gv->FLAGS & GVf_IMPORTED_CV)) {
- if ($debug_cv) {
- warn sprintf("saving extra CV &%s::%s (0x%x) from GV 0x%x\n",
- $gv->STASH->NAME, $gv->NAME, $$cv, $$gv);
- }
- $gv->bytecode;
- }
-}
-
-sub save_call_queues {
- if (begin_av()->isa("B::AV")) { # this is just to save 'use Foo;' calls
- for my $cv (begin_av()->ARRAY) {
- next unless grep { $_ eq $cv->STASH->NAME; } @packages;
- my $op = $cv->START;
-OPLOOP:
- while ($$op) {
- if ($op->name eq 'require') { # save any BEGIN that does a require
- $cv->bytecode;
- asmf "push_begin %d\n", $cv->objix;
- last OPLOOP;
- }
- $op = $op->next;
- }
- }
- }
- if (init_av()->isa("B::AV")) {
- for my $cv (init_av()->ARRAY) {
- next unless grep { $_ eq $cv->STASH->NAME; } @packages;
- $cv->bytecode;
- asmf "push_init %d\n", $cv->objix;
- }
- }
- if (end_av()->isa("B::AV")) {
- for my $cv (end_av()->ARRAY) {
- next unless grep { $_ eq $cv->STASH->NAME; } @packages;
- $cv->bytecode;
- asmf "push_end %d\n", $cv->objix;
- }
- }
-}
-
-sub symwalk {
- no strict 'refs';
- my $ok = 1 if grep { (my $name = $_[0]) =~ s/::$//; $_ eq $name;} @packages;
- if (grep { /^$_[0]/; } @packages) {
- walksymtable(\%{"$_[0]"}, "bytecodecv", \&symwalk, $_[0]);
- }
- warn "considering $_[0] ... " . ($ok ? "accepted\n" : "rejected\n")
- if $debug_bc;
- $ok;
-}
-
-sub bytecompile_main {
- my $curpad = (comppadlist->ARRAY)[1];
- my $curpadix = $curpad->objix;
- $curpad->bytecode;
- save_call_queues();
- walkoptree(main_root, "bytecode") unless ref(main_root) eq "B::NULL";
- warn "done main program, now walking symbol table\n" if $debug_bc;
- if (@packages) {
- no strict qw(refs);
- walksymtable(\%{"main::"}, "bytecodecv", \&symwalk);
- } else {
- die "No packages requested for compilation!\n";
- }
- asmf "main_root %d\n", main_root->objix;
- asmf "main_start %d\n", main_start->objix;
- asmf "curpad $curpadix\n";
- # XXX Do min_intro_pending and max_intro_pending matter?
-}
-
-sub compile {
- my @options = @_;
- my ($option, $opt, $arg);
- open(OUT, ">&STDOUT");
- binmode OUT;
- select OUT;
- OPTION:
- while ($option = shift @options) {
- if ($option =~ /^-(.)(.*)/) {
- $opt = $1;
- $arg = $2;
- } else {
- unshift @options, $option;
- last OPTION;
- }
- if ($opt eq "-" && $arg eq "-") {
- shift @options;
- last OPTION;
- } elsif ($opt eq "o") {
- $arg ||= shift @options;
- open(OUT, ">$arg") or return "$arg: $!\n";
- binmode OUT;
- } elsif ($opt eq "a") {
- $arg ||= shift @options;
- open(OUT, ">>$arg") or return "$arg: $!\n";
- binmode OUT;
- } elsif ($opt eq "D") {
- $arg ||= shift @options;
- foreach $arg (split(//, $arg)) {
- if ($arg eq "b") {
- $| = 1;
- debug(1);
- } elsif ($arg eq "o") {
- B->debug(1);
- } elsif ($arg eq "a") {
- B::Assembler::debug(1);
- } elsif ($arg eq "C") {
- $debug_cv = 1;
- }
- }
- } elsif ($opt eq "v") {
- $verbose = 1;
- } elsif ($opt eq "S") {
- $no_assemble = 1;
- } elsif ($opt eq "f") {
- $arg ||= shift @options;
- my $value = $arg !~ s/^no-//;
- $arg =~ s/-/_/g;
- my $ref = $optimise{$arg};
- if (defined($ref)) {
- $$ref = $value;
- } else {
- warn qq(ignoring unknown optimisation option "$arg"\n);
- }
- } elsif ($opt eq "O") {
- $arg = 1 if $arg eq "";
- my $ref;
- foreach $ref (values %optimise) {
- $$ref = 0;
- }
- if ($arg >= 2) {
- $bypass_nullops = 1;
- }
- if ($arg >= 1) {
- $compress_nullops = 1;
- $omit_seq = 1;
- }
- } elsif ($opt eq "u") {
- $arg ||= shift @options;
- push @packages, $arg;
- } else {
- warn qq(ignoring unknown option "$opt$arg"\n);
- }
- }
- if (! @packages) {
- warn "No package specified for compilation, assuming main::\n";
- @packages = qw(main);
- }
- if (@options) {
- die "Extraneous options left on B::Bytecode commandline: @options\n";
- } else {
- return sub {
- newasm(\&apr) unless $no_assemble;
- bytecompile_main();
- endasm() unless $no_assemble;
- };
- }
-}
-
-sub apr { print @_; }
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Bytecode - Perl compiler's bytecode backend
-
-=head1 SYNOPSIS
-
- perl -MO=Bytecode[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This compiler backend takes Perl source and generates a
-platform-independent bytecode encapsulating code to load the
-internal structures perl uses to run your program. When the
-generated bytecode is loaded in, your program is ready to run,
-reducing the time which perl would have taken to load and parse
-your program into its internal semi-compiled form. That means that
-compiling with this backend will not help improve the runtime
-execution speed of your program but may improve the start-up time.
-Depending on the environment in which your program runs this may
-or may not be a help.
-
-The resulting bytecode can be run with a special byteperl executable
-or (for non-main programs) be loaded via the C<byteload_fh> function
-in the F<B> module.
-
-=head1 OPTIONS
-
-If there are any non-option arguments, they are taken to be names of
-objects to be saved (probably doesn't work properly yet). Without
-extra arguments, it saves the main program.
-
-=over 4
-
-=item B<-ofilename>
-
-Output to filename instead of STDOUT.
-
-=item B<-afilename>
-
-Append output to filename.
-
-=item B<-->
-
-Force end of options.
-
-=item B<-f>
-
-Force optimisations on or off one at a time. Each can be preceded
-by B<no-> to turn the option off (e.g. B<-fno-compress-nullops>).
-
-=item B<-fcompress-nullops>
-
-Only fills in the necessary fields of ops which have
-been optimised away by perl's internal compiler.
-
-=item B<-fomit-sequence-numbers>
-
-Leaves out code to fill in the op_seq field of all ops
-which is only used by perl's internal compiler.
-
-=item B<-fbypass-nullops>
-
-If op->op_next ever points to a NULLOP, replaces the op_next field
-with the first non-NULLOP in the path of execution.
-
-=item B<-On>
-
-Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>.
-B<-O1> sets B<-fcompress-nullops> B<-fomit-sequence numbers>.
-B<-O2> adds B<-fbypass-nullops>.
-
-=item B<-D>
-
-Debug options (concatenated or separate flags like C<perl -D>).
-
-=item B<-Do>
-
-Prints each OP as it's processed.
-
-=item B<-Db>
-
-Print debugging information about bytecompiler progress.
-
-=item B<-Da>
-
-Tells the (bytecode) assembler to include source assembler lines
-in its output as bytecode comments.
-
-=item B<-DC>
-
-Prints each CV taken from the final symbol tree walk.
-
-=item B<-S>
-
-Output (bytecode) assembler source rather than piping it
-through the assembler and outputting bytecode.
-
-=item B<-upackage>
-
-Stores package in the output.
-
-=back
-
-=head1 EXAMPLES
-
- perl -MO=Bytecode,-O6,-ofoo.plc,-umain foo.pl
-
- perl -MO=Bytecode,-S,-umain foo.pl > foo.S
- assemble foo.S > foo.plc
-
-Note that C<assemble> lives in the C<B> subdirectory of your perl
-library directory. The utility called perlcc may also be used to
-help make use of this compiler.
-
- perl -MO=Bytecode,-uFoo,-oFoo.pmc Foo.pm
-
-=head1 BUGS
-
-Output is still huge and there are still occasional crashes during
-either compilation or ByteLoading. Current status: experimental.
-
-=head1 AUTHORS
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-Benjamin Stuhl, C<sho_pi@hotmail.com>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/C.pm b/contrib/perl5/ext/B/B/C.pm
deleted file mode 100644
index 4befe79..0000000
--- a/contrib/perl5/ext/B/B/C.pm
+++ /dev/null
@@ -1,1657 +0,0 @@
-# C.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::C::Section;
-use B ();
-use base B::Section;
-
-sub new
-{
- my $class = shift;
- my $o = $class->SUPER::new(@_);
- push(@$o,[]);
- return $o;
-}
-
-sub add
-{
- my $section = shift;
- push(@{$section->[-1]},@_);
-}
-
-sub index
-{
- my $section = shift;
- return scalar(@{$section->[-1]})-1;
-}
-
-sub output
-{
- my ($section, $fh, $format) = @_;
- my $sym = $section->symtable || {};
- my $default = $section->default;
- foreach (@{$section->[-1]})
- {
- s{(s\\_[0-9a-f]+)}{ exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
- printf $fh $format, $_;
- }
-}
-
-package B::C;
-use Exporter ();
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(output_all output_boilerplate output_main mark_unused
- init_sections set_callback save_unused_subs objsym save_context);
-
-use B qw(minus_c sv_undef walkoptree walksymtable main_root main_start peekop
- class cstring cchar svref_2object compile_stats comppadlist hash
- threadsv_names main_cv init_av opnumber amagic_generation
- AVf_REAL HEf_SVKEY);
-use B::Asmdata qw(@specialsv_name);
-
-use FileHandle;
-use Carp;
-use strict;
-use Config;
-
-my $hv_index = 0;
-my $gv_index = 0;
-my $re_index = 0;
-my $pv_index = 0;
-my $anonsub_index = 0;
-my $initsub_index = 0;
-
-my %symtable;
-my %xsub;
-my $warn_undefined_syms;
-my $verbose;
-my %unused_sub_packages;
-my $nullop_count;
-my $pv_copy_on_grow = 0;
-my ($debug_cops, $debug_av, $debug_cv, $debug_mg);
-my $max_string_len;
-
-my @threadsv_names;
-BEGIN {
- @threadsv_names = threadsv_names();
-}
-
-# Code sections
-my ($init, $decl, $symsect, $binopsect, $condopsect, $copsect,
- $padopsect, $listopsect, $logopsect, $loopsect, $opsect, $pmopsect,
- $pvopsect, $svopsect, $unopsect, $svsect, $xpvsect, $xpvavsect,
- $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect, $xpvmgsect, $xpvlvsect,
- $xrvsect, $xpvbmsect, $xpviosect );
-
-sub walk_and_save_optree;
-my $saveoptree_callback = \&walk_and_save_optree;
-sub set_callback { $saveoptree_callback = shift }
-sub saveoptree { &$saveoptree_callback(@_) }
-
-sub walk_and_save_optree {
- my ($name, $root, $start) = @_;
- walkoptree($root, "save");
- return objsym($start);
-}
-
-# Current workaround/fix for op_free() trying to free statically
-# defined OPs is to set op_seq = -1 and check for that in op_free().
-# Instead of hardwiring -1 in place of $op->seq, we use $op_seq
-# so that it can be changed back easily if necessary. In fact, to
-# stop compilers from moaning about a U16 being initialised with an
-# uncast -1 (the printf format is %d so we can't tweak it), we have
-# to "know" that op_seq is a U16 and use 65535. Ugh.
-my $op_seq = 65535;
-
-# Look this up here so we can do just a number compare
-# rather than looking up the name of every BASEOP in B::OP
-my $OP_THREADSV = opnumber('threadsv');
-
-sub savesym {
- my ($obj, $value) = @_;
- my $sym = sprintf("s\\_%x", $$obj);
- $symtable{$sym} = $value;
-}
-
-sub objsym {
- my $obj = shift;
- return $symtable{sprintf("s\\_%x", $$obj)};
-}
-
-sub getsym {
- my $sym = shift;
- my $value;
-
- return 0 if $sym eq "sym_0"; # special case
- $value = $symtable{$sym};
- if (defined($value)) {
- return $value;
- } else {
- warn "warning: undefined symbol $sym\n" if $warn_undefined_syms;
- return "UNUSED";
- }
-}
-
-sub savepv {
- my $pv = shift;
- $pv = '' unless defined $pv; # Is this sane ?
- my $pvsym = 0;
- my $pvmax = 0;
- if ($pv_copy_on_grow) {
- my $cstring = cstring($pv);
- if ($cstring ne "0") { # sic
- $pvsym = sprintf("pv%d", $pv_index++);
- $decl->add(sprintf("static char %s[] = %s;", $pvsym, $cstring));
- }
- } else {
- $pvmax = length($pv) + 1;
- }
- return ($pvsym, $pvmax);
-}
-
-sub B::OP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- my $type = $op->type;
- $nullop_count++ unless $type;
- if ($type == $OP_THREADSV) {
- # saves looking up ppaddr but it's a bit naughty to hard code this
- $init->add(sprintf("(void)find_threadsv(%s);",
- cstring($threadsv_names[$op->targ])));
- }
- $opsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x",
- ${$op->next}, ${$op->sibling}, $op->targ,
- $type, $op_seq, $op->flags, $op->private));
- my $ix = $opsect->index;
- $init->add(sprintf("op_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "&op_list[$ix]");
-}
-
-sub B::FAKEOP::new {
- my ($class, %objdata) = @_;
- bless \%objdata, $class;
-}
-
-sub B::FAKEOP::save {
- my ($op, $level) = @_;
- $opsect->add(sprintf("%s, %s, NULL, %u, %u, %u, 0x%x, 0x%x",
- $op->next, $op->sibling, $op->targ,
- $op->type, $op_seq, $op->flags, $op->private));
- my $ix = $opsect->index;
- $init->add(sprintf("op_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- return "&op_list[$ix]";
-}
-
-sub B::FAKEOP::next { $_[0]->{"next"} || 0 }
-sub B::FAKEOP::type { $_[0]->{type} || 0}
-sub B::FAKEOP::sibling { $_[0]->{sibling} || 0 }
-sub B::FAKEOP::ppaddr { $_[0]->{ppaddr} || 0 }
-sub B::FAKEOP::targ { $_[0]->{targ} || 0 }
-sub B::FAKEOP::flags { $_[0]->{flags} || 0 }
-sub B::FAKEOP::private { $_[0]->{private} || 0 }
-
-sub B::UNOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $unopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, ${$op->first}));
- my $ix = $unopsect->index;
- $init->add(sprintf("unop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&unop_list[$ix]");
-}
-
-sub B::BINOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $binopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, ${$op->first}, ${$op->last}));
- my $ix = $binopsect->index;
- $init->add(sprintf("binop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&binop_list[$ix]");
-}
-
-sub B::LISTOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $listopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, ${$op->first}, ${$op->last}));
- my $ix = $listopsect->index;
- $init->add(sprintf("listop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&listop_list[$ix]");
-}
-
-sub B::LOGOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $logopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, ${$op->first}, ${$op->other}));
- my $ix = $logopsect->index;
- $init->add(sprintf("logop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&logop_list[$ix]");
-}
-
-sub B::LOOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- #warn sprintf("LOOP: redoop %s, nextop %s, lastop %s\n",
- # peekop($op->redoop), peekop($op->nextop),
- # peekop($op->lastop)); # debug
- $loopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, s\\_%x, s\\_%x, s\\_%x",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, ${$op->first}, ${$op->last},
- ${$op->redoop}, ${$op->nextop},
- ${$op->lastop}));
- my $ix = $loopsect->index;
- $init->add(sprintf("loop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&loop_list[$ix]");
-}
-
-sub B::PVOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $pvopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, %s",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, cstring($op->pv)));
- my $ix = $pvopsect->index;
- $init->add(sprintf("pvop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- savesym($op, "(OP*)&pvop_list[$ix]");
-}
-
-sub B::SVOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- my $svsym = $op->sv->save;
- $svopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, Nullsv",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private));
- my $ix = $svopsect->index;
- $init->add(sprintf("svop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- $init->add("svop_list[$ix].op_sv = (SV*)$svsym;");
- savesym($op, "(OP*)&svop_list[$ix]");
-}
-
-sub B::PADOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- $padopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, 0",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private));
- $init->add(sprintf("padop_list[%d].op_ppaddr = %s;", $padopsect->index, $op->ppaddr));
- my $ix = $padopsect->index;
- $init->add(sprintf("padop_list[$ix].op_padix = %ld;", $op->padix));
- savesym($op, "(OP*)&padop_list[$ix]");
-}
-
-sub B::COP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- warn sprintf("COP: line %d file %s\n", $op->line, $op->file)
- if $debug_cops;
- $copsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, %s, NULL, NULL, %u, %d, %u",
- ${$op->next}, ${$op->sibling},
- $op->targ, $op->type, $op_seq, $op->flags,
- $op->private, cstring($op->label), $op->cop_seq,
- $op->arybase, $op->line));
- my $ix = $copsect->index;
- $init->add(sprintf("cop_list[$ix].op_ppaddr = %s;", $op->ppaddr));
- $init->add(sprintf("CopFILE_set(&cop_list[$ix], %s);", cstring($op->file)),
- sprintf("CopSTASHPV_set(&cop_list[$ix], %s);", cstring($op->stashpv)));
- savesym($op, "(OP*)&cop_list[$ix]");
-}
-
-sub B::PMOP::save {
- my ($op, $level) = @_;
- my $sym = objsym($op);
- return $sym if defined $sym;
- my $replroot = $op->pmreplroot;
- my $replstart = $op->pmreplstart;
- my $replrootfield = sprintf("s\\_%x", $$replroot);
- my $replstartfield = sprintf("s\\_%x", $$replstart);
- my $gvsym;
- my $ppaddr = $op->ppaddr;
- if ($$replroot) {
- # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
- # argument to a split) stores a GV in op_pmreplroot instead
- # of a substitution syntax tree. We don't want to walk that...
- if ($op->name eq "pushre") {
- $gvsym = $replroot->save;
-# warn "PMOP::save saving a pp_pushre with GV $gvsym\n"; # debug
- $replrootfield = 0;
- } else {
- $replstartfield = saveoptree("*ignore*", $replroot, $replstart);
- }
- }
- # pmnext handling is broken in perl itself, I think. Bad op_pmnext
- # fields aren't noticed in perl's runtime (unless you try reset) but we
- # segfault when trying to dereference it to find op->op_pmnext->op_type
- $pmopsect->add(sprintf("s\\_%x, s\\_%x, NULL, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %s, %s, 0, 0, 0x%x, 0x%x",
- ${$op->next}, ${$op->sibling}, $op->targ,
- $op->type, $op_seq, $op->flags, $op->private,
- ${$op->first}, ${$op->last},
- $replrootfield, $replstartfield,
- $op->pmflags, $op->pmpermflags,));
- my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
- $init->add(sprintf("$pm.op_ppaddr = %s;", $ppaddr));
- my $re = $op->precomp;
- if (defined($re)) {
- my $resym = sprintf("re%d", $re_index++);
- $decl->add(sprintf("static char *$resym = %s;", cstring($re)));
- $init->add(sprintf("$pm.op_pmregexp = pregcomp($resym, $resym + %u, &$pm);",
- length($re)));
- }
- if ($gvsym) {
- $init->add("$pm.op_pmreplroot = (OP*)$gvsym;");
- }
- savesym($op, "(OP*)&$pm");
-}
-
-sub B::SPECIAL::save {
- my ($sv) = @_;
- # special case: $$sv is not the address but an index into specialsv_list
-# warn "SPECIAL::save specialsv $$sv\n"; # debug
- my $sym = $specialsv_name[$$sv];
- if (!defined($sym)) {
- confess "unknown specialsv index $$sv passed to B::SPECIAL::save";
- }
- return $sym;
-}
-
-sub B::OBJECT::save {}
-
-sub B::NULL::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
-# warn "Saving SVt_NULL SV\n"; # debug
- # debug
- if ($$sv == 0) {
- warn "NULL::save for sv = 0 called from @{[(caller(1))[3]]}\n";
- return savesym($sv, "Nullsv /* XXX */");
- }
- $svsect->add(sprintf("0, %u, 0x%x", $sv->REFCNT , $sv->FLAGS));
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::IV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- $xpvivsect->add(sprintf("0, 0, 0, %d", $sv->IVX));
- $svsect->add(sprintf("&xpviv_list[%d], %lu, 0x%x",
- $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::NV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $val= $sv->NVX;
- $val .= '.00' if $val =~ /^-?\d+$/;
- $xpvnvsect->add(sprintf("0, 0, 0, %d, %s", $sv->IVX, $val));
- $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
- $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub savepvn {
- my ($dest,$pv) = @_;
- my @res;
- if (defined $max_string_len && length($pv) > $max_string_len) {
- push @res, sprintf("New(0,%s,%u,char);", $dest, length($pv)+1);
- my $offset = 0;
- while (length $pv) {
- my $str = substr $pv, 0, $max_string_len, '';
- push @res, sprintf("Copy(%s,$dest+$offset,%u,char);",
- cstring($str), length($str));
- $offset += length $str;
- }
- push @res, sprintf("%s[%u] = '\\0';", $dest, $offset);
- }
- else {
- push @res, sprintf("%s = savepvn(%s, %u);", $dest,
- cstring($pv), length($pv));
- }
- return @res;
-}
-
-sub B::PVLV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV;
- my $len = length($pv);
- my ($pvsym, $pvmax) = savepv($pv);
- my ($lvtarg, $lvtarg_sym);
- $xpvlvsect->add(sprintf("%s, %u, %u, %d, %g, 0, 0, %u, %u, 0, %s",
- $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX,
- $sv->TARGOFF, $sv->TARGLEN, cchar($sv->TYPE)));
- $svsect->add(sprintf("&xpvlv_list[%d], %lu, 0x%x",
- $xpvlvsect->index, $sv->REFCNT , $sv->FLAGS));
- if (!$pv_copy_on_grow) {
- $init->add(savepvn(sprintf("xpvlv_list[%d].xpv_pv",
- $xpvlvsect->index), $pv));
- }
- $sv->save_magic;
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::PVIV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV;
- my $len = length($pv);
- my ($pvsym, $pvmax) = savepv($pv);
- $xpvivsect->add(sprintf("%s, %u, %u, %d", $pvsym, $len, $pvmax, $sv->IVX));
- $svsect->add(sprintf("&xpviv_list[%d], %u, 0x%x",
- $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
- if (!$pv_copy_on_grow) {
- $init->add(savepvn(sprintf("xpviv_list[%d].xpv_pv",
- $xpvivsect->index), $pv));
- }
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::PVNV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV;
- $pv = '' unless defined $pv;
- my $len = length($pv);
- my ($pvsym, $pvmax) = savepv($pv);
- my $val= $sv->NVX;
- $val .= '.00' if $val =~ /^-?\d+$/;
- $xpvnvsect->add(sprintf("%s, %u, %u, %d, %s",
- $pvsym, $len, $pvmax, $sv->IVX, $val));
- $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
- $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
- if (!$pv_copy_on_grow) {
- $init->add(savepvn(sprintf("xpvnv_list[%d].xpv_pv",
- $xpvnvsect->index), $pv));
- }
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::BM::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV . "\0" . $sv->TABLE;
- my $len = length($pv);
- $xpvbmsect->add(sprintf("0, %u, %u, %d, %s, 0, 0, %d, %u, 0x%x",
- $len, $len + 258, $sv->IVX, $sv->NVX,
- $sv->USEFUL, $sv->PREVIOUS, $sv->RARE));
- $svsect->add(sprintf("&xpvbm_list[%d], %lu, 0x%x",
- $xpvbmsect->index, $sv->REFCNT , $sv->FLAGS));
- $sv->save_magic;
- $init->add(savepvn(sprintf("xpvbm_list[%d].xpv_pv",
- $xpvbmsect->index), $pv),
- sprintf("xpvbm_list[%d].xpv_cur = %u;",
- $xpvbmsect->index, $len - 257));
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::PV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV;
- my $len = length($pv);
- my ($pvsym, $pvmax) = savepv($pv);
- $xpvsect->add(sprintf("%s, %u, %u", $pvsym, $len, $pvmax));
- $svsect->add(sprintf("&xpv_list[%d], %lu, 0x%x",
- $xpvsect->index, $sv->REFCNT , $sv->FLAGS));
- if (!$pv_copy_on_grow) {
- $init->add(savepvn(sprintf("xpv_list[%d].xpv_pv",
- $xpvsect->index), $pv));
- }
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub B::PVMG::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $pv = $sv->PV;
- my $len = length($pv);
- my ($pvsym, $pvmax) = savepv($pv);
- $xpvmgsect->add(sprintf("%s, %u, %u, %d, %s, 0, 0",
- $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX));
- $svsect->add(sprintf("&xpvmg_list[%d], %lu, 0x%x",
- $xpvmgsect->index, $sv->REFCNT , $sv->FLAGS));
- if (!$pv_copy_on_grow) {
- $init->add(savepvn(sprintf("xpvmg_list[%d].xpv_pv",
- $xpvmgsect->index), $pv));
- }
- $sym = savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
- $sv->save_magic;
- return $sym;
-}
-
-sub B::PVMG::save_magic {
- my ($sv) = @_;
- #warn sprintf("saving magic for %s (0x%x)\n", class($sv), $$sv); # debug
- my $stash = $sv->SvSTASH;
- $stash->save;
- if ($$stash) {
- warn sprintf("xmg_stash = %s (0x%x)\n", $stash->NAME, $$stash)
- if $debug_mg;
- # XXX Hope stash is already going to be saved.
- $init->add(sprintf("SvSTASH(s\\_%x) = s\\_%x;", $$sv, $$stash));
- }
- my @mgchain = $sv->MAGIC;
- my ($mg, $type, $obj, $ptr,$len,$ptrsv);
- foreach $mg (@mgchain) {
- $type = $mg->TYPE;
- $obj = $mg->OBJ;
- $ptr = $mg->PTR;
- $len=$mg->LENGTH;
- if ($debug_mg) {
- warn sprintf("magic %s (0x%x), obj %s (0x%x), type %s, ptr %s\n",
- class($sv), $$sv, class($obj), $$obj,
- cchar($type), cstring($ptr));
- }
- $obj->save;
- if ($len == HEf_SVKEY){
- #The pointer is an SV*
- $ptrsv=svref_2object($ptr)->save;
- $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s,(char *) %s, %d);",
- $$sv, $$obj, cchar($type),$ptrsv,$len));
- }else{
- $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
- $$sv, $$obj, cchar($type),cstring($ptr),$len));
- }
- }
-}
-
-sub B::RV::save {
- my ($sv) = @_;
- my $sym = objsym($sv);
- return $sym if defined $sym;
- my $rv = $sv->RV->save;
- $rv =~ s/^\([AGHS]V\s*\*\)\s*(\&sv_list.*)$/$1/;
- $xrvsect->add($rv);
- $svsect->add(sprintf("&xrv_list[%d], %lu, 0x%x",
- $xrvsect->index, $sv->REFCNT , $sv->FLAGS));
- return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
-}
-
-sub try_autoload {
- my ($cvstashname, $cvname) = @_;
- warn sprintf("No definition for sub %s::%s\n", $cvstashname, $cvname);
- # Handle AutoLoader classes explicitly. Any more general AUTOLOAD
- # use should be handled by the class itself.
- no strict 'refs';
- my $isa = \@{"$cvstashname\::ISA"};
- if (grep($_ eq "AutoLoader", @$isa)) {
- warn "Forcing immediate load of sub derived from AutoLoader\n";
- # Tweaked version of AutoLoader::AUTOLOAD
- my $dir = $cvstashname;
- $dir =~ s(::)(/)g;
- eval { require "auto/$dir/$cvname.al" };
- if ($@) {
- warn qq(failed require "auto/$dir/$cvname.al": $@\n);
- return 0;
- } else {
- return 1;
- }
- }
-}
-sub Dummy_initxs{};
-sub B::CV::save {
- my ($cv) = @_;
- my $sym = objsym($cv);
- if (defined($sym)) {
-# warn sprintf("CV 0x%x already saved as $sym\n", $$cv); # debug
- return $sym;
- }
- # Reserve a place in svsect and xpvcvsect and record indices
- my $gv = $cv->GV;
- my ($cvname, $cvstashname);
- if ($$gv){
- $cvname = $gv->NAME;
- $cvstashname = $gv->STASH->NAME;
- }
- my $root = $cv->ROOT;
- my $cvxsub = $cv->XSUB;
- #INIT is removed from the symbol table, so this call must come
- # from PL_initav->save. Re-bootstrapping will push INIT back in
- # so nullop should be sent.
- if ($cvxsub && ($cvname ne "INIT")) {
- my $egv = $gv->EGV;
- my $stashname = $egv->STASH->NAME;
- if ($cvname eq "bootstrap")
- {
- my $file = $gv->FILE;
- $decl->add("/* bootstrap $file */");
- warn "Bootstrap $stashname $file\n";
- $xsub{$stashname}='Dynamic';
- # $xsub{$stashname}='Static' unless $xsub{$stashname};
- return qq/NULL/;
- }
- warn sprintf("stub for XSUB $cvstashname\:\:$cvname CV 0x%x\n", $$cv) if $debug_cv;
- return qq/(perl_get_cv("$stashname\:\:$cvname",TRUE))/;
- }
- if ($cvxsub && $cvname eq "INIT") {
- no strict 'refs';
- return svref_2object(\&Dummy_initxs)->save;
- }
- my $sv_ix = $svsect->index + 1;
- $svsect->add("svix$sv_ix");
- my $xpvcv_ix = $xpvcvsect->index + 1;
- $xpvcvsect->add("xpvcvix$xpvcv_ix");
- # Save symbol now so that GvCV() doesn't recurse back to us via CvGV()
- $sym = savesym($cv, "&sv_list[$sv_ix]");
- warn sprintf("saving $cvstashname\:\:$cvname CV 0x%x as $sym\n", $$cv) if $debug_cv;
- if (!$$root && !$cvxsub) {
- if (try_autoload($cvstashname, $cvname)) {
- # Recalculate root and xsub
- $root = $cv->ROOT;
- $cvxsub = $cv->XSUB;
- if ($$root || $cvxsub) {
- warn "Successful forced autoload\n";
- }
- }
- }
- my $startfield = 0;
- my $padlist = $cv->PADLIST;
- my $pv = $cv->PV;
- my $xsub = 0;
- my $xsubany = "Nullany";
- if ($$root) {
- warn sprintf("saving op tree for CV 0x%x, root = 0x%x\n",
- $$cv, $$root) if $debug_cv;
- my $ppname = "";
- if ($$gv) {
- my $stashname = $gv->STASH->NAME;
- my $gvname = $gv->NAME;
- if ($gvname ne "__ANON__") {
- $ppname = (${$gv->FORM} == $$cv) ? "pp_form_" : "pp_sub_";
- $ppname .= ($stashname eq "main") ?
- $gvname : "$stashname\::$gvname";
- $ppname =~ s/::/__/g;
- if ($gvname eq "INIT"){
- $ppname .= "_$initsub_index";
- $initsub_index++;
- }
- }
- }
- if (!$ppname) {
- $ppname = "pp_anonsub_$anonsub_index";
- $anonsub_index++;
- }
- $startfield = saveoptree($ppname, $root, $cv->START, $padlist->ARRAY);
- warn sprintf("done saving op tree for CV 0x%x, name %s, root 0x%x\n",
- $$cv, $ppname, $$root) if $debug_cv;
- if ($$padlist) {
- warn sprintf("saving PADLIST 0x%x for CV 0x%x\n",
- $$padlist, $$cv) if $debug_cv;
- $padlist->save;
- warn sprintf("done saving PADLIST 0x%x for CV 0x%x\n",
- $$padlist, $$cv) if $debug_cv;
- }
- }
- else {
- warn sprintf("No definition for sub %s::%s (unable to autoload)\n",
- $cvstashname, $cvname); # debug
- }
- $pv = '' unless defined $pv; # Avoid use of undef warnings
- $symsect->add(sprintf("xpvcvix%d\t%s, %u, 0, %d, %s, 0, Nullhv, Nullhv, %s, s\\_%x, $xsub, $xsubany, Nullgv, \"\", %d, s\\_%x, (CV*)s\\_%x, 0x%x",
- $xpvcv_ix, cstring($pv), length($pv), $cv->IVX,
- $cv->NVX, $startfield, ${$cv->ROOT}, $cv->DEPTH,
- $$padlist, ${$cv->OUTSIDE}, $cv->CvFLAGS));
-
- if (${$cv->OUTSIDE} == ${main_cv()}){
- $init->add(sprintf("CvOUTSIDE(s\\_%x)=PL_main_cv;",$$cv));
- $init->add(sprintf("SvREFCNT_inc(PL_main_cv);"));
- }
-
- if ($$gv) {
- $gv->save;
- $init->add(sprintf("CvGV(s\\_%x) = s\\_%x;",$$cv,$$gv));
- warn sprintf("done saving GV 0x%x for CV 0x%x\n",
- $$gv, $$cv) if $debug_cv;
- }
- $init->add(sprintf("CvFILE($sym) = %s;", cstring($cv->FILE)));
- my $stash = $cv->STASH;
- if ($$stash) {
- $stash->save;
- $init->add(sprintf("CvSTASH(s\\_%x) = s\\_%x;", $$cv, $$stash));
- warn sprintf("done saving STASH 0x%x for CV 0x%x\n",
- $$stash, $$cv) if $debug_cv;
- }
- $symsect->add(sprintf("svix%d\t(XPVCV*)&xpvcv_list[%u], %lu, 0x%x",
- $sv_ix, $xpvcv_ix, $cv->REFCNT +1 , $cv->FLAGS));
- return $sym;
-}
-
-sub B::GV::save {
- my ($gv) = @_;
- my $sym = objsym($gv);
- if (defined($sym)) {
- #warn sprintf("GV 0x%x already saved as $sym\n", $$gv); # debug
- return $sym;
- } else {
- my $ix = $gv_index++;
- $sym = savesym($gv, "gv_list[$ix]");
- #warn sprintf("Saving GV 0x%x as $sym\n", $$gv); # debug
- }
- my $is_empty = $gv->is_empty;
- my $gvname = $gv->NAME;
- my $name = cstring($gv->STASH->NAME . "::" . $gvname);
- #warn "GV name is $name\n"; # debug
- my $egvsym;
- unless ($is_empty) {
- my $egv = $gv->EGV;
- if ($$gv != $$egv) {
- #warn(sprintf("EGV name is %s, saving it now\n",
- # $egv->STASH->NAME . "::" . $egv->NAME)); # debug
- $egvsym = $egv->save;
- }
- }
- $init->add(qq[$sym = gv_fetchpv($name, TRUE, SVt_PV);],
- sprintf("SvFLAGS($sym) = 0x%x;", $gv->FLAGS),
- sprintf("GvFLAGS($sym) = 0x%x;", $gv->GvFLAGS));
- $init->add(sprintf("GvLINE($sym) = %u;", $gv->LINE)) unless $is_empty;
-
- # Shouldn't need to do save_magic since gv_fetchpv handles that
- #$gv->save_magic;
- my $refcnt = $gv->REFCNT + 1;
- $init->add(sprintf("SvREFCNT($sym) += %u;", $refcnt - 1)) if $refcnt > 1;
-
- return $sym if $is_empty;
-
- my $gvrefcnt = $gv->GvREFCNT;
- if ($gvrefcnt > 1) {
- $init->add(sprintf("GvREFCNT($sym) += %u;", $gvrefcnt - 1));
- }
- if (defined($egvsym)) {
- # Shared glob *foo = *bar
- $init->add("gp_free($sym);",
- "GvGP($sym) = GvGP($egvsym);");
- } elsif ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) {
- # Don't save subfields of special GVs (*_, *1, *# and so on)
-# warn "GV::save saving subfields\n"; # debug
- my $gvsv = $gv->SV;
- if ($$gvsv) {
- $gvsv->save;
- $init->add(sprintf("GvSV($sym) = s\\_%x;", $$gvsv));
-# warn "GV::save \$$name\n"; # debug
- }
- my $gvav = $gv->AV;
- if ($$gvav) {
- $gvav->save;
- $init->add(sprintf("GvAV($sym) = s\\_%x;", $$gvav));
-# warn "GV::save \@$name\n"; # debug
- }
- my $gvhv = $gv->HV;
- if ($$gvhv) {
- $gvhv->save;
- $init->add(sprintf("GvHV($sym) = s\\_%x;", $$gvhv));
-# warn "GV::save \%$name\n"; # debug
- }
- my $gvcv = $gv->CV;
- if ($$gvcv) {
- my $origname=cstring($gvcv->GV->EGV->STASH->NAME .
- "::" . $gvcv->GV->EGV->NAME);
- if (0 && $gvcv->XSUB && $name ne $origname) { #XSUB alias
- # must save as a 'stub' so newXS() has a CV to populate
- $init->add("{ CV *cv;");
- $init->add("\tcv=perl_get_cv($origname,TRUE);");
- $init->add("\tGvCV($sym)=cv;");
- $init->add("\tSvREFCNT_inc((SV *)cv);");
- $init->add("}");
- } else {
- $init->add(sprintf("GvCV($sym) = (CV*)(%s);", $gvcv->save));
-# warn "GV::save &$name\n"; # debug
- }
- }
- $init->add(sprintf("GvFILE($sym) = %s;", cstring($gv->FILE)));
-# warn "GV::save GvFILE(*$name)\n"; # debug
- my $gvform = $gv->FORM;
- if ($$gvform) {
- $gvform->save;
- $init->add(sprintf("GvFORM($sym) = (CV*)s\\_%x;", $$gvform));
-# warn "GV::save GvFORM(*$name)\n"; # debug
- }
- my $gvio = $gv->IO;
- if ($$gvio) {
- $gvio->save;
- $init->add(sprintf("GvIOp($sym) = s\\_%x;", $$gvio));
-# warn "GV::save GvIO(*$name)\n"; # debug
- }
- }
- return $sym;
-}
-sub B::AV::save {
- my ($av) = @_;
- my $sym = objsym($av);
- return $sym if defined $sym;
- my $avflags = $av->AvFLAGS;
- $xpvavsect->add(sprintf("0, -1, -1, 0, 0.0, 0, Nullhv, 0, 0, 0x%x",
- $avflags));
- $svsect->add(sprintf("&xpvav_list[%d], %lu, 0x%x",
- $xpvavsect->index, $av->REFCNT , $av->FLAGS));
- my $sv_list_index = $svsect->index;
- my $fill = $av->FILL;
- $av->save_magic;
- warn sprintf("saving AV 0x%x FILL=$fill AvFLAGS=0x%x", $$av, $avflags)
- if $debug_av;
- # XXX AVf_REAL is wrong test: need to save comppadlist but not stack
- #if ($fill > -1 && ($avflags & AVf_REAL)) {
- if ($fill > -1) {
- my @array = $av->ARRAY;
- if ($debug_av) {
- my $el;
- my $i = 0;
- foreach $el (@array) {
- warn sprintf("AV 0x%x[%d] = %s 0x%x\n",
- $$av, $i++, class($el), $$el);
- }
- }
- my @names = map($_->save, @array);
- # XXX Better ways to write loop?
- # Perhaps svp[0] = ...; svp[1] = ...; svp[2] = ...;
- # Perhaps I32 i = 0; svp[i++] = ...; svp[i++] = ...; svp[i++] = ...;
- $init->add("{",
- "\tSV **svp;",
- "\tAV *av = (AV*)&sv_list[$sv_list_index];",
- "\tav_extend(av, $fill);",
- "\tsvp = AvARRAY(av);",
- map("\t*svp++ = (SV*)$_;", @names),
- "\tAvFILLp(av) = $fill;",
- "}");
- } else {
- my $max = $av->MAX;
- $init->add("av_extend((AV*)&sv_list[$sv_list_index], $max);")
- if $max > -1;
- }
- return savesym($av, "(AV*)&sv_list[$sv_list_index]");
-}
-
-sub B::HV::save {
- my ($hv) = @_;
- my $sym = objsym($hv);
- return $sym if defined $sym;
- my $name = $hv->NAME;
- if ($name) {
- # It's a stash
-
- # A perl bug means HvPMROOT isn't altered when a PMOP is freed. Usually
- # the only symptom is that sv_reset tries to reset the PMf_USED flag of
- # a trashed op but we look at the trashed op_type and segfault.
- #my $adpmroot = ${$hv->PMROOT};
- my $adpmroot = 0;
- $decl->add("static HV *hv$hv_index;");
- # XXX Beware of weird package names containing double-quotes, \n, ...?
- $init->add(qq[hv$hv_index = gv_stashpv("$name", TRUE);]);
- if ($adpmroot) {
- $init->add(sprintf("HvPMROOT(hv$hv_index) = (PMOP*)s\\_%x;",
- $adpmroot));
- }
- $sym = savesym($hv, "hv$hv_index");
- $hv_index++;
- return $sym;
- }
- # It's just an ordinary HV
- $xpvhvsect->add(sprintf("0, 0, %d, 0, 0.0, 0, Nullhv, %d, 0, 0, 0",
- $hv->MAX, $hv->RITER));
- $svsect->add(sprintf("&xpvhv_list[%d], %lu, 0x%x",
- $xpvhvsect->index, $hv->REFCNT , $hv->FLAGS));
- my $sv_list_index = $svsect->index;
- my @contents = $hv->ARRAY;
- if (@contents) {
- my $i;
- for ($i = 1; $i < @contents; $i += 2) {
- $contents[$i] = $contents[$i]->save;
- }
- $init->add("{", "\tHV *hv = (HV*)&sv_list[$sv_list_index];");
- while (@contents) {
- my ($key, $value) = splice(@contents, 0, 2);
- $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
- cstring($key),length($key),$value, hash($key)));
-# $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
-# cstring($key),length($key),$value, 0));
- }
- $init->add("}");
- }
- $hv->save_magic();
- return savesym($hv, "(HV*)&sv_list[$sv_list_index]");
-}
-
-sub B::IO::save {
- my ($io) = @_;
- my $sym = objsym($io);
- return $sym if defined $sym;
- my $pv = $io->PV;
- $pv = '' unless defined $pv;
- my $len = length($pv);
- $xpviosect->add(sprintf("0, %u, %u, %d, %s, 0, 0, 0, 0, 0, %d, %d, %d, %d, %s, Nullgv, %s, Nullgv, %s, Nullgv, %d, %s, 0x%x",
- $len, $len+1, $io->IVX, $io->NVX, $io->LINES,
- $io->PAGE, $io->PAGE_LEN, $io->LINES_LEFT,
- cstring($io->TOP_NAME), cstring($io->FMT_NAME),
- cstring($io->BOTTOM_NAME), $io->SUBPROCESS,
- cchar($io->IoTYPE), $io->IoFLAGS));
- $svsect->add(sprintf("&xpvio_list[%d], %lu, 0x%x",
- $xpviosect->index, $io->REFCNT , $io->FLAGS));
- $sym = savesym($io, sprintf("(IO*)&sv_list[%d]", $svsect->index));
- my ($field, $fsym);
- foreach $field (qw(TOP_GV FMT_GV BOTTOM_GV)) {
- $fsym = $io->$field();
- if ($$fsym) {
- $init->add(sprintf("Io$field($sym) = (GV*)s\\_%x;", $$fsym));
- $fsym->save;
- }
- }
- $io->save_magic;
- return $sym;
-}
-
-sub B::SV::save {
- my $sv = shift;
- # This is where we catch an honest-to-goodness Nullsv (which gets
- # blessed into B::SV explicitly) and any stray erroneous SVs.
- return 0 unless $$sv;
- confess sprintf("cannot save that type of SV: %s (0x%x)\n",
- class($sv), $$sv);
-}
-
-sub output_all {
- my $init_name = shift;
- my $section;
- my @sections = ($opsect, $unopsect, $binopsect, $logopsect, $condopsect,
- $listopsect, $pmopsect, $svopsect, $padopsect, $pvopsect,
- $loopsect, $copsect, $svsect, $xpvsect,
- $xpvavsect, $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect,
- $xpvmgsect, $xpvlvsect, $xrvsect, $xpvbmsect, $xpviosect);
- $symsect->output(\*STDOUT, "#define %s\n");
- print "\n";
- output_declarations();
- foreach $section (@sections) {
- my $lines = $section->index + 1;
- if ($lines) {
- my $name = $section->name;
- my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
- print "Static $typename ${name}_list[$lines];\n";
- }
- }
- $decl->output(\*STDOUT, "%s\n");
- print "\n";
- foreach $section (@sections) {
- my $lines = $section->index + 1;
- if ($lines) {
- my $name = $section->name;
- my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
- printf "static %s %s_list[%u] = {\n", $typename, $name, $lines;
- $section->output(\*STDOUT, "\t{ %s },\n");
- print "};\n\n";
- }
- }
-
- print <<"EOT";
-static int $init_name()
-{
- dTARG;
- dSP;
-EOT
- $init->output(\*STDOUT, "\t%s\n");
- print "\treturn 0;\n}\n";
- if ($verbose) {
- warn compile_stats();
- warn "NULLOP count: $nullop_count\n";
- }
-}
-
-sub output_declarations {
- print <<'EOT';
-#ifdef BROKEN_STATIC_REDECL
-#define Static extern
-#else
-#define Static static
-#endif /* BROKEN_STATIC_REDECL */
-
-#ifdef BROKEN_UNION_INIT
-/*
- * Cribbed from cv.h with ANY (a union) replaced by void*.
- * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
- */
-typedef struct {
- char * xpv_pv; /* pointer to malloced string */
- STRLEN xpv_cur; /* length of xp_pv as a C string */
- STRLEN xpv_len; /* allocated size */
- IV xof_off; /* integer value */
- NV xnv_nv; /* numeric value, if any */
- MAGIC* xmg_magic; /* magic for scalar array */
- HV* xmg_stash; /* class package */
-
- HV * xcv_stash;
- OP * xcv_start;
- OP * xcv_root;
- void (*xcv_xsub) (pTHXo_ CV*);
- ANY xcv_xsubany;
- GV * xcv_gv;
- char * xcv_file;
- long xcv_depth; /* >= 2 indicates recursive call */
- AV * xcv_padlist;
- CV * xcv_outside;
-#ifdef USE_THREADS
- perl_mutex *xcv_mutexp;
- struct perl_thread *xcv_owner; /* current owner thread */
-#endif /* USE_THREADS */
- cv_flags_t xcv_flags;
-} XPVCV_or_similar;
-#define ANYINIT(i) i
-#else
-#define XPVCV_or_similar XPVCV
-#define ANYINIT(i) {i}
-#endif /* BROKEN_UNION_INIT */
-#define Nullany ANYINIT(0)
-
-#define UNUSED 0
-#define sym_0 0
-
-EOT
- print "static GV *gv_list[$gv_index];\n" if $gv_index;
- print "\n";
-}
-
-
-sub output_boilerplate {
- print <<'EOT';
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Workaround for mapstart: the only op which needs a different ppaddr */
-#undef Perl_pp_mapstart
-#define Perl_pp_mapstart Perl_pp_grepstart
-#define XS_DynaLoader_boot_DynaLoader boot_DynaLoader
-EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
-
-static void xs_init (pTHX);
-static void dl_init (pTHX);
-static PerlInterpreter *my_perl;
-EOT
-}
-
-sub output_main {
- print <<'EOT';
-int
-main(int argc, char **argv, char **env)
-{
- int exitstatus;
- int i;
- char **fakeargv;
-
- PERL_SYS_INIT3(&argc,&argv,&env);
-
- if (!PL_do_undump) {
- my_perl = perl_alloc();
- if (!my_perl)
- exit(1);
- perl_construct( my_perl );
- PL_perl_destruct_level = 0;
- }
-
-#ifdef CSH
- if (!PL_cshlen)
- PL_cshlen = strlen(PL_cshname);
-#endif
-
-#ifdef ALLOW_PERL_OPTIONS
-#define EXTRA_OPTIONS 2
-#else
-#define EXTRA_OPTIONS 3
-#endif /* ALLOW_PERL_OPTIONS */
- New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
- fakeargv[0] = argv[0];
- fakeargv[1] = "-e";
- fakeargv[2] = "";
-#ifndef ALLOW_PERL_OPTIONS
- fakeargv[3] = "--";
-#endif /* ALLOW_PERL_OPTIONS */
- for (i = 1; i < argc; i++)
- fakeargv[i + EXTRA_OPTIONS] = argv[i];
- fakeargv[argc + EXTRA_OPTIONS] = 0;
-
- exitstatus = perl_parse(my_perl, xs_init, argc + EXTRA_OPTIONS,
- fakeargv, NULL);
- if (exitstatus)
- exit( exitstatus );
-
- sv_setpv(GvSV(gv_fetchpv("0", TRUE, SVt_PV)), argv[0]);
- PL_main_cv = PL_compcv;
- PL_compcv = 0;
-
- exitstatus = perl_init();
- if (exitstatus)
- exit( exitstatus );
- dl_init(aTHX);
-
- exitstatus = perl_run( my_perl );
-
- perl_destruct( my_perl );
- perl_free( my_perl );
-
- PERL_SYS_TERM();
-
- exit( exitstatus );
-}
-
-/* yanked from perl.c */
-static void
-xs_init(pTHX)
-{
- char *file = __FILE__;
- dTARG;
- dSP;
-EOT
- print "\n#ifdef USE_DYNAMIC_LOADING";
- print qq/\n\tnewXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);/;
- print "\n#endif\n" ;
- # delete $xsub{'DynaLoader'};
- delete $xsub{'UNIVERSAL'};
- print("/* bootstrapping code*/\n\tSAVETMPS;\n");
- print("\ttarg=sv_newmortal();\n");
- print "#ifdef DYNALOADER_BOOTSTRAP\n";
- print "\tPUSHMARK(sp);\n";
- print qq/\tXPUSHp("DynaLoader",strlen("DynaLoader"));\n/;
- print qq/\tPUTBACK;\n/;
- print "\tboot_DynaLoader(aTHX_ NULL);\n";
- print qq/\tSPAGAIN;\n/;
- print "#endif\n";
- foreach my $stashname (keys %xsub){
- if ($xsub{$stashname} ne 'Dynamic') {
- my $stashxsub=$stashname;
- $stashxsub =~ s/::/__/g;
- print "\tPUSHMARK(sp);\n";
- print qq/\tXPUSHp("$stashname",strlen("$stashname"));\n/;
- print qq/\tPUTBACK;\n/;
- print "\tboot_$stashxsub(aTHX_ NULL);\n";
- print qq/\tSPAGAIN;\n/;
- }
- }
- print("\tFREETMPS;\n/* end bootstrapping code */\n");
- print "}\n";
-
-print <<'EOT';
-static void
-dl_init(pTHX)
-{
- char *file = __FILE__;
- dTARG;
- dSP;
-EOT
- print("/* Dynamicboot strapping code*/\n\tSAVETMPS;\n");
- print("\ttarg=sv_newmortal();\n");
- foreach my $stashname (@DynaLoader::dl_modules) {
- warn "Loaded $stashname\n";
- if (exists($xsub{$stashname}) && $xsub{$stashname} eq 'Dynamic') {
- my $stashxsub=$stashname;
- $stashxsub =~ s/::/__/g;
- print "\tPUSHMARK(sp);\n";
- print qq/\tXPUSHp("$stashname",/,length($stashname),qq/);\n/;
- print qq/\tPUTBACK;\n/;
- print "#ifdef DYNALOADER_BOOTSTRAP\n";
- warn "bootstrapping $stashname added to xs_init\n";
- print qq/\tperl_call_method("bootstrap",G_DISCARD);\n/;
- print "\n#else\n";
- print "\tboot_$stashxsub(aTHX_ NULL);\n";
- print "#endif\n";
- print qq/\tSPAGAIN;\n/;
- }
- }
- print("\tFREETMPS;\n/* end Dynamic bootstrapping code */\n");
- print "}\n";
-}
-sub dump_symtable {
- # For debugging
- my ($sym, $val);
- warn "----Symbol table:\n";
- while (($sym, $val) = each %symtable) {
- warn "$sym => $val\n";
- }
- warn "---End of symbol table\n";
-}
-
-sub save_object {
- my $sv;
- foreach $sv (@_) {
- svref_2object($sv)->save;
- }
-}
-
-sub Dummy_BootStrap { }
-
-sub B::GV::savecv
-{
- my $gv = shift;
- my $package=$gv->STASH->NAME;
- my $name = $gv->NAME;
- my $cv = $gv->CV;
- my $sv = $gv->SV;
- my $av = $gv->AV;
- my $hv = $gv->HV;
-
- # We may be looking at this package just because it is a branch in the
- # symbol table which is on the path to a package which we need to save
- # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
- #
- return unless ($unused_sub_packages{$package});
- return unless ($$cv || $$av || $$sv || $$hv);
- $gv->save;
-}
-
-sub mark_package
-{
- my $package = shift;
- unless ($unused_sub_packages{$package})
- {
- no strict 'refs';
- $unused_sub_packages{$package} = 1;
- if (defined @{$package.'::ISA'})
- {
- foreach my $isa (@{$package.'::ISA'})
- {
- if ($isa eq 'DynaLoader')
- {
- unless (defined(&{$package.'::bootstrap'}))
- {
- warn "Forcing bootstrap of $package\n";
- eval { $package->bootstrap };
- }
- }
-# else
- {
- unless ($unused_sub_packages{$isa})
- {
- warn "$isa saved (it is in $package\'s \@ISA)\n";
- mark_package($isa);
- }
- }
- }
- }
- }
- return 1;
-}
-
-sub should_save
-{
- no strict qw(vars refs);
- my $package = shift;
- $package =~ s/::$//;
- return $unused_sub_packages{$package} = 0 if ($package =~ /::::/); # skip ::::ISA::CACHE etc.
- # warn "Considering $package\n";#debug
- foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages))
- {
- # If this package is a prefix to something we are saving, traverse it
- # but do not mark it for saving if it is not already
- # e.g. to get to Getopt::Long we need to traverse Getopt but need
- # not save Getopt
- return 1 if ($u =~ /^$package\:\:/);
- }
- if (exists $unused_sub_packages{$package})
- {
- # warn "Cached $package is ".$unused_sub_packages{$package}."\n";
- delete_unsaved_hashINC($package) unless $unused_sub_packages{$package} ;
- return $unused_sub_packages{$package};
- }
- # Omit the packages which we use (and which cause grief
- # because of fancy "goto &$AUTOLOAD" stuff).
- # XXX Surely there must be a nicer way to do this.
- if ($package eq "FileHandle" || $package eq "Config" ||
- $package eq "SelectSaver" || $package =~/^(B|IO)::/)
- {
- delete_unsaved_hashINC($package);
- return $unused_sub_packages{$package} = 0;
- }
- # Now see if current package looks like an OO class this is probably too strong.
- foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE))
- {
- if (UNIVERSAL::can($package, $m))
- {
- warn "$package has method $m: saving package\n";#debug
- return mark_package($package);
- }
- }
- delete_unsaved_hashINC($package);
- return $unused_sub_packages{$package} = 0;
-}
-sub delete_unsaved_hashINC{
- my $packname=shift;
- $packname =~ s/\:\:/\//g;
- $packname .= '.pm';
-# warn "deleting $packname" if $INC{$packname} ;# debug
- delete $INC{$packname};
-}
-sub walkpackages
-{
- my ($symref, $recurse, $prefix) = @_;
- my $sym;
- my $ref;
- no strict 'vars';
- local(*glob);
- $prefix = '' unless defined $prefix;
- while (($sym, $ref) = each %$symref)
- {
- *glob = $ref;
- if ($sym =~ /::$/)
- {
- $sym = $prefix . $sym;
- if ($sym ne "main::" && $sym ne "<none>::" && &$recurse($sym))
- {
- walkpackages(\%glob, $recurse, $sym);
- }
- }
- }
-}
-
-
-sub save_unused_subs
-{
- no strict qw(refs);
- &descend_marked_unused;
- warn "Prescan\n";
- walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
- warn "Saving methods\n";
- walksymtable(\%{"main::"}, "savecv", \&should_save);
-}
-
-sub save_context
-{
- my $curpad_nam = (comppadlist->ARRAY)[0]->save;
- my $curpad_sym = (comppadlist->ARRAY)[1]->save;
- my $inc_hv = svref_2object(\%INC)->save;
- my $inc_av = svref_2object(\@INC)->save;
- my $amagic_generate= amagic_generation;
- $init->add( "PL_curpad = AvARRAY($curpad_sym);",
- "GvHV(PL_incgv) = $inc_hv;",
- "GvAV(PL_incgv) = $inc_av;",
- "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
- "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
- "PL_amagic_generation= $amagic_generate;" );
-}
-
-sub descend_marked_unused {
- foreach my $pack (keys %unused_sub_packages)
- {
- mark_package($pack);
- }
-}
-
-sub save_main {
- warn "Starting compile\n";
- warn "Walking tree\n";
- seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
- walkoptree(main_root, "save");
- warn "done main optree, walking symtable for extras\n" if $debug_cv;
- save_unused_subs();
- my $init_av = init_av->save;
- $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
- sprintf("PL_main_start = s\\_%x;", ${main_start()}),
- "PL_initav = (AV *) $init_av;");
- save_context();
- warn "Writing output\n";
- output_boilerplate();
- print "\n";
- output_all("perl_init");
- print "\n";
- output_main();
-}
-
-sub init_sections {
- my @sections = (init => \$init, decl => \$decl, sym => \$symsect,
- binop => \$binopsect, condop => \$condopsect,
- cop => \$copsect, padop => \$padopsect,
- listop => \$listopsect, logop => \$logopsect,
- loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
- pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
- sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
- xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
- xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
- xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
- xrv => \$xrvsect, xpvbm => \$xpvbmsect,
- xpvio => \$xpviosect);
- my ($name, $sectref);
- while (($name, $sectref) = splice(@sections, 0, 2)) {
- $$sectref = new B::C::Section $name, \%symtable, 0;
- }
-}
-
-sub mark_unused
-{
- my ($arg,$val) = @_;
- $unused_sub_packages{$arg} = $val;
-}
-
-sub compile {
- my @options = @_;
- my ($option, $opt, $arg);
- OPTION:
- while ($option = shift @options) {
- if ($option =~ /^-(.)(.*)/) {
- $opt = $1;
- $arg = $2;
- } else {
- unshift @options, $option;
- last OPTION;
- }
- if ($opt eq "-" && $arg eq "-") {
- shift @options;
- last OPTION;
- }
- if ($opt eq "w") {
- $warn_undefined_syms = 1;
- } elsif ($opt eq "D") {
- $arg ||= shift @options;
- foreach $arg (split(//, $arg)) {
- if ($arg eq "o") {
- B->debug(1);
- } elsif ($arg eq "c") {
- $debug_cops = 1;
- } elsif ($arg eq "A") {
- $debug_av = 1;
- } elsif ($arg eq "C") {
- $debug_cv = 1;
- } elsif ($arg eq "M") {
- $debug_mg = 1;
- } else {
- warn "ignoring unknown debug option: $arg\n";
- }
- }
- } elsif ($opt eq "o") {
- $arg ||= shift @options;
- open(STDOUT, ">$arg") or return "$arg: $!\n";
- } elsif ($opt eq "v") {
- $verbose = 1;
- } elsif ($opt eq "u") {
- $arg ||= shift @options;
- mark_unused($arg,undef);
- } elsif ($opt eq "f") {
- $arg ||= shift @options;
- if ($arg eq "cog") {
- $pv_copy_on_grow = 1;
- } elsif ($arg eq "no-cog") {
- $pv_copy_on_grow = 0;
- }
- } elsif ($opt eq "O") {
- $arg = 1 if $arg eq "";
- $pv_copy_on_grow = 0;
- if ($arg >= 1) {
- # Optimisations for -O1
- $pv_copy_on_grow = 1;
- }
- } elsif ($opt eq "l") {
- $max_string_len = $arg;
- }
- }
- init_sections();
- if (@options) {
- return sub {
- my $objname;
- foreach $objname (@options) {
- eval "save_object(\\$objname)";
- }
- output_all();
- }
- } else {
- return sub { save_main() };
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::C - Perl compiler's C backend
-
-=head1 SYNOPSIS
-
- perl -MO=C[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This compiler backend takes Perl source and generates C source code
-corresponding to the internal structures that perl uses to run
-your program. When the generated C source is compiled and run, it
-cuts out the time which perl would have taken to load and parse
-your program into its internal semi-compiled form. That means that
-compiling with this backend will not help improve the runtime
-execution speed of your program but may improve the start-up time.
-Depending on the environment in which your program runs this may be
-either a help or a hindrance.
-
-=head1 OPTIONS
-
-If there are any non-option arguments, they are taken to be
-names of objects to be saved (probably doesn't work properly yet).
-Without extra arguments, it saves the main program.
-
-=over 4
-
-=item B<-ofilename>
-
-Output to filename instead of STDOUT
-
-=item B<-v>
-
-Verbose compilation (currently gives a few compilation statistics).
-
-=item B<-->
-
-Force end of options
-
-=item B<-uPackname>
-
-Force apparently unused subs from package Packname to be compiled.
-This allows programs to use eval "foo()" even when sub foo is never
-seen to be used at compile time. The down side is that any subs which
-really are never used also have code generated. This option is
-necessary, for example, if you have a signal handler foo which you
-initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
-to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
-options. The compiler tries to figure out which packages may possibly
-have subs in which need compiling but the current version doesn't do
-it very well. In particular, it is confused by nested packages (i.e.
-of the form C<A::B>) where package C<A> does not contain any subs.
-
-=item B<-D>
-
-Debug options (concatenated or separate flags like C<perl -D>).
-
-=item B<-Do>
-
-OPs, prints each OP as it's processed
-
-=item B<-Dc>
-
-COPs, prints COPs as processed (incl. file & line num)
-
-=item B<-DA>
-
-prints AV information on saving
-
-=item B<-DC>
-
-prints CV information on saving
-
-=item B<-DM>
-
-prints MAGIC information on saving
-
-=item B<-f>
-
-Force optimisations on or off one at a time.
-
-=item B<-fcog>
-
-Copy-on-grow: PVs declared and initialised statically.
-
-=item B<-fno-cog>
-
-No copy-on-grow.
-
-=item B<-On>
-
-Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. Currently,
-B<-O1> and higher set B<-fcog>.
-
-=item B<-llimit>
-
-Some C compilers impose an arbitrary limit on the length of string
-constants (e.g. 2048 characters for Microsoft Visual C++). The
-B<-llimit> options tells the C backend not to generate string literals
-exceeding that limit.
-
-=back
-
-=head1 EXAMPLES
-
- perl -MO=C,-ofoo.c foo.pl
- perl cc_harness -o foo foo.c
-
-Note that C<cc_harness> lives in the C<B> subdirectory of your perl
-library directory. The utility called C<perlcc> may also be used to
-help make use of this compiler.
-
- perl -MO=C,-v,-DcA,-l2048 bar.pl > /dev/null
-
-=head1 BUGS
-
-Plenty. Current status: experimental.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/CC.pm b/contrib/perl5/ext/B/B/CC.pm
deleted file mode 100644
index 51922ee..0000000
--- a/contrib/perl5/ext/B/B/CC.pm
+++ /dev/null
@@ -1,2002 +0,0 @@
-# CC.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::CC;
-use Config;
-use strict;
-use B qw(main_start main_root class comppadlist peekop svref_2object
- timing_info init_av sv_undef amagic_generation
- OPf_WANT_LIST OPf_WANT OPf_MOD OPf_STACKED OPf_SPECIAL
- OPpASSIGN_BACKWARDS OPpLVAL_INTRO OPpDEREF_AV OPpDEREF_HV
- OPpDEREF OPpFLIP_LINENUM G_ARRAY G_SCALAR
- CXt_NULL CXt_SUB CXt_EVAL CXt_LOOP CXt_SUBST CXt_BLOCK
- );
-use B::C qw(save_unused_subs objsym init_sections mark_unused
- output_all output_boilerplate output_main);
-use B::Bblock qw(find_leaders);
-use B::Stackobj qw(:types :flags);
-
-# These should probably be elsewhere
-# Flags for $op->flags
-
-my $module; # module name (when compiled with -m)
-my %done; # hash keyed by $$op of leaders of basic blocks
- # which have already been done.
-my $leaders; # ref to hash of basic block leaders. Keys are $$op
- # addresses, values are the $op objects themselves.
-my @bblock_todo; # list of leaders of basic blocks that need visiting
- # sometime.
-my @cc_todo; # list of tuples defining what PP code needs to be
- # saved (e.g. CV, main or PMOP repl code). Each tuple
- # is [$name, $root, $start, @padlist]. PMOP repl code
- # tuples inherit padlist.
-my @stack; # shadows perl's stack when contents are known.
- # Values are objects derived from class B::Stackobj
-my @pad; # Lexicals in current pad as Stackobj-derived objects
-my @padlist; # Copy of current padlist so PMOP repl code can find it
-my @cxstack; # Shadows the (compile-time) cxstack for next,last,redo
-my $jmpbuf_ix = 0; # Next free index for dynamically allocated jmpbufs
-my %constobj; # OP_CONST constants as Stackobj-derived objects
- # keyed by $$sv.
-my $need_freetmps = 0; # We may postpone FREETMPS to the end of each basic
- # block or even to the end of each loop of blocks,
- # depending on optimisation options.
-my $know_op = 0; # Set when C variable op already holds the right op
- # (from an immediately preceding DOOP(ppname)).
-my $errors = 0; # Number of errors encountered
-my %skip_stack; # Hash of PP names which don't need write_back_stack
-my %skip_lexicals; # Hash of PP names which don't need write_back_lexicals
-my %skip_invalidate; # Hash of PP names which don't need invalidate_lexicals
-my %ignore_op; # Hash of ops which do nothing except returning op_next
-my %need_curcop; # Hash of ops which need PL_curcop
-
-my %lexstate; #state of padsvs at the start of a bblock
-
-BEGIN {
- foreach (qw(pp_scalar pp_regcmaybe pp_lineseq pp_scope pp_null)) {
- $ignore_op{$_} = 1;
- }
-}
-
-my ($module_name);
-my ($debug_op, $debug_stack, $debug_cxstack, $debug_pad, $debug_runtime,
- $debug_shadow, $debug_queue, $debug_lineno, $debug_timings);
-
-# Optimisation options. On the command line, use hyphens instead of
-# underscores for compatibility with gcc-style options. We use
-# underscores here because they are OK in (strict) barewords.
-my ($freetmps_each_bblock, $freetmps_each_loop, $omit_taint);
-my %optimise = (freetmps_each_bblock => \$freetmps_each_bblock,
- freetmps_each_loop => \$freetmps_each_loop,
- omit_taint => \$omit_taint);
-# perl patchlevel to generate code for (defaults to current patchlevel)
-my $patchlevel = int(0.5 + 1000 * ($] - 5));
-
-# Could rewrite push_runtime() and output_runtime() to use a
-# temporary file if memory is at a premium.
-my $ppname; # name of current fake PP function
-my $runtime_list_ref;
-my $declare_ref; # Hash ref keyed by C variable type of declarations.
-
-my @pp_list; # list of [$ppname, $runtime_list_ref, $declare_ref]
- # tuples to be written out.
-
-my ($init, $decl);
-
-sub init_hash { map { $_ => 1 } @_ }
-
-#
-# Initialise the hashes for the default PP functions where we can avoid
-# either write_back_stack, write_back_lexicals or invalidate_lexicals.
-#
-%skip_lexicals = init_hash qw(pp_enter pp_enterloop);
-%skip_invalidate = init_hash qw(pp_enter pp_enterloop);
-%need_curcop = init_hash qw(pp_rv2gv pp_bless pp_repeat pp_sort pp_caller
- pp_reset pp_rv2cv pp_entereval pp_require pp_dofile
- pp_entertry pp_enterloop pp_enteriter pp_entersub
- pp_enter pp_method);
-
-sub debug {
- if ($debug_runtime) {
- warn(@_);
- } else {
- my @tmp=@_;
- runtime(map { chomp; "/* $_ */"} @tmp);
- }
-}
-
-sub declare {
- my ($type, $var) = @_;
- push(@{$declare_ref->{$type}}, $var);
-}
-
-sub push_runtime {
- push(@$runtime_list_ref, @_);
- warn join("\n", @_) . "\n" if $debug_runtime;
-}
-
-sub save_runtime {
- push(@pp_list, [$ppname, $runtime_list_ref, $declare_ref]);
-}
-
-sub output_runtime {
- my $ppdata;
- print qq(#include "cc_runtime.h"\n);
- foreach $ppdata (@pp_list) {
- my ($name, $runtime, $declare) = @$ppdata;
- print "\nstatic\nCCPP($name)\n{\n";
- my ($type, $varlist, $line);
- while (($type, $varlist) = each %$declare) {
- print "\t$type ", join(", ", @$varlist), ";\n";
- }
- foreach $line (@$runtime) {
- print $line, "\n";
- }
- print "}\n";
- }
-}
-
-sub runtime {
- my $line;
- foreach $line (@_) {
- push_runtime("\t$line");
- }
-}
-
-sub init_pp {
- $ppname = shift;
- $runtime_list_ref = [];
- $declare_ref = {};
- runtime("dSP;");
- declare("I32", "oldsave");
- declare("SV", "**svp");
- map { declare("SV", "*$_") } qw(sv src dst left right);
- declare("MAGIC", "*mg");
- $decl->add("static OP * $ppname (pTHX);");
- debug "init_pp: $ppname\n" if $debug_queue;
-}
-
-# Initialise runtime_callback function for Stackobj class
-BEGIN { B::Stackobj::set_callback(\&runtime) }
-
-# Initialise saveoptree_callback for B::C class
-sub cc_queue {
- my ($name, $root, $start, @pl) = @_;
- debug "cc_queue: name $name, root $root, start $start, padlist (@pl)\n"
- if $debug_queue;
- if ($name eq "*ignore*") {
- $name = 0;
- } else {
- push(@cc_todo, [$name, $root, $start, (@pl ? @pl : @padlist)]);
- }
- my $fakeop = new B::FAKEOP ("next" => 0, sibling => 0, ppaddr => $name);
- $start = $fakeop->save;
- debug "cc_queue: name $name returns $start\n" if $debug_queue;
- return $start;
-}
-BEGIN { B::C::set_callback(\&cc_queue) }
-
-sub valid_int { $_[0]->{flags} & VALID_INT }
-sub valid_double { $_[0]->{flags} & VALID_DOUBLE }
-sub valid_numeric { $_[0]->{flags} & (VALID_INT | VALID_DOUBLE) }
-sub valid_sv { $_[0]->{flags} & VALID_SV }
-
-sub top_int { @stack ? $stack[-1]->as_int : "TOPi" }
-sub top_double { @stack ? $stack[-1]->as_double : "TOPn" }
-sub top_numeric { @stack ? $stack[-1]->as_numeric : "TOPn" }
-sub top_sv { @stack ? $stack[-1]->as_sv : "TOPs" }
-sub top_bool { @stack ? $stack[-1]->as_bool : "SvTRUE(TOPs)" }
-
-sub pop_int { @stack ? (pop @stack)->as_int : "POPi" }
-sub pop_double { @stack ? (pop @stack)->as_double : "POPn" }
-sub pop_numeric { @stack ? (pop @stack)->as_numeric : "POPn" }
-sub pop_sv { @stack ? (pop @stack)->as_sv : "POPs" }
-sub pop_bool {
- if (@stack) {
- return ((pop @stack)->as_bool);
- } else {
- # Careful: POPs has an auto-decrement and SvTRUE evaluates
- # its argument more than once.
- runtime("sv = POPs;");
- return "SvTRUE(sv)";
- }
-}
-
-sub write_back_lexicals {
- my $avoid = shift || 0;
- debug "write_back_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
- if $debug_shadow;
- my $lex;
- foreach $lex (@pad) {
- next unless ref($lex);
- $lex->write_back unless $lex->{flags} & $avoid;
- }
-}
-
-sub save_or_restore_lexical_state {
- my $bblock=shift;
- unless( exists $lexstate{$bblock}){
- foreach my $lex (@pad) {
- next unless ref($lex);
- ${$lexstate{$bblock}}{$lex->{iv}} = $lex->{flags} ;
- }
- }
- else {
- foreach my $lex (@pad) {
- next unless ref($lex);
- my $old_flags=${$lexstate{$bblock}}{$lex->{iv}} ;
- next if ( $old_flags eq $lex->{flags});
- if (($old_flags & VALID_SV) && !($lex->{flags} & VALID_SV)){
- $lex->write_back;
- }
- if (($old_flags & VALID_DOUBLE) && !($lex->{flags} & VALID_DOUBLE)){
- $lex->load_double;
- }
- if (($old_flags & VALID_INT) && !($lex->{flags} & VALID_INT)){
- $lex->load_int;
- }
- }
- }
-}
-
-sub write_back_stack {
- my $obj;
- return unless @stack;
- runtime(sprintf("EXTEND(sp, %d);", scalar(@stack)));
- foreach $obj (@stack) {
- runtime(sprintf("PUSHs((SV*)%s);", $obj->as_sv));
- }
- @stack = ();
-}
-
-sub invalidate_lexicals {
- my $avoid = shift || 0;
- debug "invalidate_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
- if $debug_shadow;
- my $lex;
- foreach $lex (@pad) {
- next unless ref($lex);
- $lex->invalidate unless $lex->{flags} & $avoid;
- }
-}
-
-sub reload_lexicals {
- my $lex;
- foreach $lex (@pad) {
- next unless ref($lex);
- my $type = $lex->{type};
- if ($type == T_INT) {
- $lex->as_int;
- } elsif ($type == T_DOUBLE) {
- $lex->as_double;
- } else {
- $lex->as_sv;
- }
- }
-}
-
-{
- package B::Pseudoreg;
- #
- # This class allocates pseudo-registers (OK, so they're C variables).
- #
- my %alloc; # Keyed by variable name. A value of 1 means the
- # variable has been declared. A value of 2 means
- # it's in use.
-
- sub new_scope { %alloc = () }
-
- sub new ($$$) {
- my ($class, $type, $prefix) = @_;
- my ($ptr, $i, $varname, $status, $obj);
- $prefix =~ s/^(\**)//;
- $ptr = $1;
- $i = 0;
- do {
- $varname = "$prefix$i";
- $status = $alloc{$varname};
- } while $status == 2;
- if ($status != 1) {
- # Not declared yet
- B::CC::declare($type, "$ptr$varname");
- $alloc{$varname} = 2; # declared and in use
- }
- $obj = bless \$varname, $class;
- return $obj;
- }
- sub DESTROY {
- my $obj = shift;
- $alloc{$$obj} = 1; # no longer in use but still declared
- }
-}
-{
- package B::Shadow;
- #
- # This class gives a standard API for a perl object to shadow a
- # C variable and only generate reloads/write-backs when necessary.
- #
- # Use $obj->load($foo) instead of runtime("shadowed_c_var = foo").
- # Use $obj->write_back whenever shadowed_c_var needs to be up to date.
- # Use $obj->invalidate whenever an unknown function may have
- # set shadow itself.
-
- sub new {
- my ($class, $write_back) = @_;
- # Object fields are perl shadow variable, validity flag
- # (for *C* variable) and callback sub for write_back
- # (passed perl shadow variable as argument).
- bless [undef, 1, $write_back], $class;
- }
- sub load {
- my ($obj, $newval) = @_;
- $obj->[1] = 0; # C variable no longer valid
- $obj->[0] = $newval;
- }
- sub write_back {
- my $obj = shift;
- if (!($obj->[1])) {
- $obj->[1] = 1; # C variable will now be valid
- &{$obj->[2]}($obj->[0]);
- }
- }
- sub invalidate { $_[0]->[1] = 0 } # force C variable to be invalid
-}
-my $curcop = new B::Shadow (sub {
- my $opsym = shift->save;
- runtime("PL_curcop = (COP*)$opsym;");
-});
-
-#
-# Context stack shadowing. Mimics stuff in pp_ctl.c, cop.h and so on.
-#
-sub dopoptoloop {
- my $cxix = $#cxstack;
- while ($cxix >= 0 && $cxstack[$cxix]->{type} != CXt_LOOP) {
- $cxix--;
- }
- debug "dopoptoloop: returning $cxix" if $debug_cxstack;
- return $cxix;
-}
-
-sub dopoptolabel {
- my $label = shift;
- my $cxix = $#cxstack;
- while ($cxix >= 0 &&
- ($cxstack[$cxix]->{type} != CXt_LOOP ||
- $cxstack[$cxix]->{label} ne $label)) {
- $cxix--;
- }
- debug "dopoptolabel: returning $cxix" if $debug_cxstack;
- return $cxix;
-}
-
-sub error {
- my $format = shift;
- my $file = $curcop->[0]->file;
- my $line = $curcop->[0]->line;
- $errors++;
- if (@_) {
- warn sprintf("%s:%d: $format\n", $file, $line, @_);
- } else {
- warn sprintf("%s:%d: %s\n", $file, $line, $format);
- }
-}
-
-#
-# Load pad takes (the elements of) a PADLIST as arguments and loads
-# up @pad with Stackobj-derived objects which represent those lexicals.
-# If/when perl itself can generate type information (my int $foo) then
-# we'll take advantage of that here. Until then, we'll use various hacks
-# to tell the compiler when we want a lexical to be a particular type
-# or to be a register.
-#
-sub load_pad {
- my ($namelistav, $valuelistav) = @_;
- @padlist = @_;
- my @namelist = $namelistav->ARRAY;
- my @valuelist = $valuelistav->ARRAY;
- my $ix;
- @pad = ();
- debug "load_pad: $#namelist names, $#valuelist values\n" if $debug_pad;
- # Temporary lexicals don't get named so it's possible for @valuelist
- # to be strictly longer than @namelist. We count $ix up to the end of
- # @valuelist but index into @namelist for the name. Any temporaries which
- # run off the end of @namelist will make $namesv undefined and we treat
- # that the same as having an explicit SPECIAL sv_undef object in @namelist.
- # [XXX If/when @_ becomes a lexical, we must start at 0 here.]
- for ($ix = 1; $ix < @valuelist; $ix++) {
- my $namesv = $namelist[$ix];
- my $type = T_UNKNOWN;
- my $flags = 0;
- my $name = "tmp$ix";
- my $class = class($namesv);
- if (!defined($namesv) || $class eq "SPECIAL") {
- # temporaries have &PL_sv_undef instead of a PVNV for a name
- $flags = VALID_SV|TEMPORARY|REGISTER;
- } else {
- if ($namesv->PV =~ /^\$(.*)_([di])(r?)$/) {
- $name = $1;
- if ($2 eq "i") {
- $type = T_INT;
- $flags = VALID_SV|VALID_INT;
- } elsif ($2 eq "d") {
- $type = T_DOUBLE;
- $flags = VALID_SV|VALID_DOUBLE;
- }
- $flags |= REGISTER if $3;
- }
- }
- $pad[$ix] = new B::Stackobj::Padsv ($type, $flags, $ix,
- "i_$name", "d_$name");
-
- debug sprintf("PL_curpad[$ix] = %s\n", $pad[$ix]->peek) if $debug_pad;
- }
-}
-
-sub declare_pad {
- my $ix;
- for ($ix = 1; $ix <= $#pad; $ix++) {
- my $type = $pad[$ix]->{type};
- declare("IV", $type == T_INT ?
- sprintf("%s=0",$pad[$ix]->{iv}):$pad[$ix]->{iv}) if $pad[$ix]->save_int;
- declare("double", $type == T_DOUBLE ?
- sprintf("%s = 0",$pad[$ix]->{nv}):$pad[$ix]->{nv} )if $pad[$ix]->save_double;
-
- }
-}
-#
-# Debugging stuff
-#
-sub peek_stack { sprintf "stack = %s\n", join(" ", map($_->minipeek, @stack)) }
-
-#
-# OP stuff
-#
-
-sub label {
- my $op = shift;
- # XXX Preserve original label name for "real" labels?
- return sprintf("lab_%x", $$op);
-}
-
-sub write_label {
- my $op = shift;
- push_runtime(sprintf(" %s:", label($op)));
-}
-
-sub loadop {
- my $op = shift;
- my $opsym = $op->save;
- runtime("PL_op = $opsym;") unless $know_op;
- return $opsym;
-}
-
-sub doop {
- my $op = shift;
- my $ppname = $op->ppaddr;
- my $sym = loadop($op);
- runtime("DOOP($ppname);");
- $know_op = 1;
- return $sym;
-}
-
-sub gimme {
- my $op = shift;
- my $flags = $op->flags;
- return (($flags & OPf_WANT) ? (($flags & OPf_WANT)== OPf_WANT_LIST? G_ARRAY:G_SCALAR) : "dowantarray()");
-}
-
-#
-# Code generation for PP code
-#
-
-sub pp_null {
- my $op = shift;
- return $op->next;
-}
-
-sub pp_stub {
- my $op = shift;
- my $gimme = gimme($op);
- if ($gimme != G_ARRAY) {
- my $obj= new B::Stackobj::Const(sv_undef);
- push(@stack, $obj);
- # XXX Change to push a constant sv_undef Stackobj onto @stack
- #write_back_stack();
- #runtime("if ($gimme != G_ARRAY) XPUSHs(&PL_sv_undef);");
- }
- return $op->next;
-}
-
-sub pp_unstack {
- my $op = shift;
- @stack = ();
- runtime("PP_UNSTACK;");
- return $op->next;
-}
-
-sub pp_and {
- my $op = shift;
- my $next = $op->next;
- reload_lexicals();
- unshift(@bblock_todo, $next);
- if (@stack >= 1) {
- my $bool = pop_bool();
- write_back_stack();
- save_or_restore_lexical_state($$next);
- runtime(sprintf("if (!$bool) {XPUSHs(&PL_sv_no); goto %s;}", label($next)));
- } else {
- save_or_restore_lexical_state($$next);
- runtime(sprintf("if (!%s) goto %s;", top_bool(), label($next)),
- "*sp--;");
- }
- return $op->other;
-}
-
-sub pp_or {
- my $op = shift;
- my $next = $op->next;
- reload_lexicals();
- unshift(@bblock_todo, $next);
- if (@stack >= 1) {
- my $bool = pop_bool @stack;
- write_back_stack();
- save_or_restore_lexical_state($$next);
- runtime(sprintf("if (%s) { XPUSHs(&PL_sv_yes); goto %s; }",
- $bool, label($next)));
- } else {
- save_or_restore_lexical_state($$next);
- runtime(sprintf("if (%s) goto %s;", top_bool(), label($next)),
- "*sp--;");
- }
- return $op->other;
-}
-
-sub pp_cond_expr {
- my $op = shift;
- my $false = $op->next;
- unshift(@bblock_todo, $false);
- reload_lexicals();
- my $bool = pop_bool();
- write_back_stack();
- save_or_restore_lexical_state($$false);
- runtime(sprintf("if (!$bool) goto %s;", label($false)));
- return $op->other;
-}
-
-sub pp_padsv {
- my $op = shift;
- my $ix = $op->targ;
- push(@stack, $pad[$ix]);
- if ($op->flags & OPf_MOD) {
- my $private = $op->private;
- if ($private & OPpLVAL_INTRO) {
- runtime("SAVECLEARSV(PL_curpad[$ix]);");
- } elsif ($private & OPpDEREF) {
- runtime(sprintf("vivify_ref(PL_curpad[%d], %d);",
- $ix, $private & OPpDEREF));
- $pad[$ix]->invalidate;
- }
- }
- return $op->next;
-}
-
-sub pp_const {
- my $op = shift;
- my $sv = $op->sv;
- my $obj;
- # constant could be in the pad (under useithreads)
- if ($$sv) {
- $obj = $constobj{$$sv};
- if (!defined($obj)) {
- $obj = $constobj{$$sv} = new B::Stackobj::Const ($sv);
- }
- }
- else {
- $obj = $pad[$op->targ];
- }
- push(@stack, $obj);
- return $op->next;
-}
-
-sub pp_nextstate {
- my $op = shift;
- $curcop->load($op);
- @stack = ();
- debug(sprintf("%s:%d\n", $op->file, $op->line)) if $debug_lineno;
- runtime("TAINT_NOT;") unless $omit_taint;
- runtime("sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;");
- if ($freetmps_each_bblock || $freetmps_each_loop) {
- $need_freetmps = 1;
- } else {
- runtime("FREETMPS;");
- }
- return $op->next;
-}
-
-sub pp_dbstate {
- my $op = shift;
- $curcop->invalidate; # XXX?
- return default_pp($op);
-}
-
-#default_pp will handle this:
-#sub pp_bless { $curcop->write_back; default_pp(@_) }
-#sub pp_repeat { $curcop->write_back; default_pp(@_) }
-# The following subs need $curcop->write_back if we decide to support arybase:
-# pp_pos, pp_substr, pp_index, pp_rindex, pp_aslice, pp_lslice, pp_splice
-#sub pp_caller { $curcop->write_back; default_pp(@_) }
-#sub pp_reset { $curcop->write_back; default_pp(@_) }
-
-sub pp_rv2gv{
- my $op =shift;
- $curcop->write_back;
- write_back_lexicals() unless $skip_lexicals{$ppname};
- write_back_stack() unless $skip_stack{$ppname};
- my $sym=doop($op);
- if ($op->private & OPpDEREF) {
- $init->add(sprintf("((UNOP *)$sym)->op_first = $sym;"));
- $init->add(sprintf("((UNOP *)$sym)->op_type = %d;",
- $op->first->type));
- }
- return $op->next;
-}
-sub pp_sort {
- my $op = shift;
- my $ppname = $op->ppaddr;
- if ( $op->flags & OPf_SPECIAL && $op->flags & OPf_STACKED){
- #this indicates the sort BLOCK Array case
- #ugly surgery required.
- my $root=$op->first->sibling->first;
- my $start=$root->first;
- $op->first->save;
- $op->first->sibling->save;
- $root->save;
- my $sym=$start->save;
- my $fakeop=cc_queue("pp_sort".$$op,$root,$start);
- $init->add(sprintf("(%s)->op_next=%s;",$sym,$fakeop));
- }
- $curcop->write_back;
- write_back_lexicals();
- write_back_stack();
- doop($op);
- return $op->next;
-}
-
-sub pp_gv {
- my $op = shift;
- my $gvsym;
- if ($Config{useithreads}) {
- $gvsym = $pad[$op->padix]->as_sv;
- }
- else {
- $gvsym = $op->gv->save;
- }
- write_back_stack();
- runtime("XPUSHs((SV*)$gvsym);");
- return $op->next;
-}
-
-sub pp_gvsv {
- my $op = shift;
- my $gvsym;
- if ($Config{useithreads}) {
- $gvsym = $pad[$op->padix]->as_sv;
- }
- else {
- $gvsym = $op->gv->save;
- }
- write_back_stack();
- if ($op->private & OPpLVAL_INTRO) {
- runtime("XPUSHs(save_scalar($gvsym));");
- } else {
- runtime("XPUSHs(GvSV($gvsym));");
- }
- return $op->next;
-}
-
-sub pp_aelemfast {
- my $op = shift;
- my $gvsym;
- if ($Config{useithreads}) {
- $gvsym = $pad[$op->padix]->as_sv;
- }
- else {
- $gvsym = $op->gv->save;
- }
- my $ix = $op->private;
- my $flag = $op->flags & OPf_MOD;
- write_back_stack();
- runtime("svp = av_fetch(GvAV($gvsym), $ix, $flag);",
- "PUSHs(svp ? *svp : &PL_sv_undef);");
- return $op->next;
-}
-
-sub int_binop {
- my ($op, $operator) = @_;
- if ($op->flags & OPf_STACKED) {
- my $right = pop_int();
- if (@stack >= 1) {
- my $left = top_int();
- $stack[-1]->set_int(&$operator($left, $right));
- } else {
- runtime(sprintf("sv_setiv(TOPs, %s);",&$operator("TOPi", $right)));
- }
- } else {
- my $targ = $pad[$op->targ];
- my $right = new B::Pseudoreg ("IV", "riv");
- my $left = new B::Pseudoreg ("IV", "liv");
- runtime(sprintf("$$right = %s; $$left = %s;", pop_int(), pop_int));
- $targ->set_int(&$operator($$left, $$right));
- push(@stack, $targ);
- }
- return $op->next;
-}
-
-sub INTS_CLOSED () { 0x1 }
-sub INT_RESULT () { 0x2 }
-sub NUMERIC_RESULT () { 0x4 }
-
-sub numeric_binop {
- my ($op, $operator, $flags) = @_;
- my $force_int = 0;
- $force_int ||= ($flags & INT_RESULT);
- $force_int ||= ($flags & INTS_CLOSED && @stack >= 2
- && valid_int($stack[-2]) && valid_int($stack[-1]));
- if ($op->flags & OPf_STACKED) {
- my $right = pop_numeric();
- if (@stack >= 1) {
- my $left = top_numeric();
- if ($force_int) {
- $stack[-1]->set_int(&$operator($left, $right));
- } else {
- $stack[-1]->set_numeric(&$operator($left, $right));
- }
- } else {
- if ($force_int) {
- my $rightruntime = new B::Pseudoreg ("IV", "riv");
- runtime(sprintf("$$rightruntime = %s;",$right));
- runtime(sprintf("sv_setiv(TOPs, %s);",
- &$operator("TOPi", $$rightruntime)));
- } else {
- my $rightruntime = new B::Pseudoreg ("double", "rnv");
- runtime(sprintf("$$rightruntime = %s;",$right));
- runtime(sprintf("sv_setnv(TOPs, %s);",
- &$operator("TOPn",$$rightruntime)));
- }
- }
- } else {
- my $targ = $pad[$op->targ];
- $force_int ||= ($targ->{type} == T_INT);
- if ($force_int) {
- my $right = new B::Pseudoreg ("IV", "riv");
- my $left = new B::Pseudoreg ("IV", "liv");
- runtime(sprintf("$$right = %s; $$left = %s;",
- pop_numeric(), pop_numeric));
- $targ->set_int(&$operator($$left, $$right));
- } else {
- my $right = new B::Pseudoreg ("double", "rnv");
- my $left = new B::Pseudoreg ("double", "lnv");
- runtime(sprintf("$$right = %s; $$left = %s;",
- pop_numeric(), pop_numeric));
- $targ->set_numeric(&$operator($$left, $$right));
- }
- push(@stack, $targ);
- }
- return $op->next;
-}
-
-sub pp_ncmp {
- my ($op) = @_;
- if ($op->flags & OPf_STACKED) {
- my $right = pop_numeric();
- if (@stack >= 1) {
- my $left = top_numeric();
- runtime sprintf("if (%s > %s){",$left,$right);
- $stack[-1]->set_int(1);
- $stack[-1]->write_back();
- runtime sprintf("}else if (%s < %s ) {",$left,$right);
- $stack[-1]->set_int(-1);
- $stack[-1]->write_back();
- runtime sprintf("}else if (%s == %s) {",$left,$right);
- $stack[-1]->set_int(0);
- $stack[-1]->write_back();
- runtime sprintf("}else {");
- $stack[-1]->set_sv("&PL_sv_undef");
- runtime "}";
- } else {
- my $rightruntime = new B::Pseudoreg ("double", "rnv");
- runtime(sprintf("$$rightruntime = %s;",$right));
- runtime sprintf(qq/if ("TOPn" > %s){/,$rightruntime);
- runtime sprintf("sv_setiv(TOPs,1);");
- runtime sprintf(qq/}else if ( "TOPn" < %s ) {/,$$rightruntime);
- runtime sprintf("sv_setiv(TOPs,-1);");
- runtime sprintf(qq/} else if ("TOPn" == %s) {/,$$rightruntime);
- runtime sprintf("sv_setiv(TOPs,0);");
- runtime sprintf(qq/}else {/);
- runtime sprintf("sv_setiv(TOPs,&PL_sv_undef;");
- runtime "}";
- }
- } else {
- my $targ = $pad[$op->targ];
- my $right = new B::Pseudoreg ("double", "rnv");
- my $left = new B::Pseudoreg ("double", "lnv");
- runtime(sprintf("$$right = %s; $$left = %s;",
- pop_numeric(), pop_numeric));
- runtime sprintf("if (%s > %s){",$$left,$$right);
- $targ->set_int(1);
- $targ->write_back();
- runtime sprintf("}else if (%s < %s ) {",$$left,$$right);
- $targ->set_int(-1);
- $targ->write_back();
- runtime sprintf("}else if (%s == %s) {",$$left,$$right);
- $targ->set_int(0);
- $targ->write_back();
- runtime sprintf("}else {");
- $targ->set_sv("&PL_sv_undef");
- runtime "}";
- push(@stack, $targ);
- }
- return $op->next;
-}
-
-sub sv_binop {
- my ($op, $operator, $flags) = @_;
- if ($op->flags & OPf_STACKED) {
- my $right = pop_sv();
- if (@stack >= 1) {
- my $left = top_sv();
- if ($flags & INT_RESULT) {
- $stack[-1]->set_int(&$operator($left, $right));
- } elsif ($flags & NUMERIC_RESULT) {
- $stack[-1]->set_numeric(&$operator($left, $right));
- } else {
- # XXX Does this work?
- runtime(sprintf("sv_setsv($left, %s);",
- &$operator($left, $right)));
- $stack[-1]->invalidate;
- }
- } else {
- my $f;
- if ($flags & INT_RESULT) {
- $f = "sv_setiv";
- } elsif ($flags & NUMERIC_RESULT) {
- $f = "sv_setnv";
- } else {
- $f = "sv_setsv";
- }
- runtime(sprintf("%s(TOPs, %s);", $f, &$operator("TOPs", $right)));
- }
- } else {
- my $targ = $pad[$op->targ];
- runtime(sprintf("right = %s; left = %s;", pop_sv(), pop_sv));
- if ($flags & INT_RESULT) {
- $targ->set_int(&$operator("left", "right"));
- } elsif ($flags & NUMERIC_RESULT) {
- $targ->set_numeric(&$operator("left", "right"));
- } else {
- # XXX Does this work?
- runtime(sprintf("sv_setsv(%s, %s);",
- $targ->as_sv, &$operator("left", "right")));
- $targ->invalidate;
- }
- push(@stack, $targ);
- }
- return $op->next;
-}
-
-sub bool_int_binop {
- my ($op, $operator) = @_;
- my $right = new B::Pseudoreg ("IV", "riv");
- my $left = new B::Pseudoreg ("IV", "liv");
- runtime(sprintf("$$right = %s; $$left = %s;", pop_int(), pop_int()));
- my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
- $bool->set_int(&$operator($$left, $$right));
- push(@stack, $bool);
- return $op->next;
-}
-
-sub bool_numeric_binop {
- my ($op, $operator) = @_;
- my $right = new B::Pseudoreg ("double", "rnv");
- my $left = new B::Pseudoreg ("double", "lnv");
- runtime(sprintf("$$right = %s; $$left = %s;",
- pop_numeric(), pop_numeric()));
- my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
- $bool->set_numeric(&$operator($$left, $$right));
- push(@stack, $bool);
- return $op->next;
-}
-
-sub bool_sv_binop {
- my ($op, $operator) = @_;
- runtime(sprintf("right = %s; left = %s;", pop_sv(), pop_sv()));
- my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
- $bool->set_numeric(&$operator("left", "right"));
- push(@stack, $bool);
- return $op->next;
-}
-
-sub infix_op {
- my $opname = shift;
- return sub { "$_[0] $opname $_[1]" }
-}
-
-sub prefix_op {
- my $opname = shift;
- return sub { sprintf("%s(%s)", $opname, join(", ", @_)) }
-}
-
-BEGIN {
- my $plus_op = infix_op("+");
- my $minus_op = infix_op("-");
- my $multiply_op = infix_op("*");
- my $divide_op = infix_op("/");
- my $modulo_op = infix_op("%");
- my $lshift_op = infix_op("<<");
- my $rshift_op = infix_op(">>");
- my $scmp_op = prefix_op("sv_cmp");
- my $seq_op = prefix_op("sv_eq");
- my $sne_op = prefix_op("!sv_eq");
- my $slt_op = sub { "sv_cmp($_[0], $_[1]) < 0" };
- my $sgt_op = sub { "sv_cmp($_[0], $_[1]) > 0" };
- my $sle_op = sub { "sv_cmp($_[0], $_[1]) <= 0" };
- my $sge_op = sub { "sv_cmp($_[0], $_[1]) >= 0" };
- my $eq_op = infix_op("==");
- my $ne_op = infix_op("!=");
- my $lt_op = infix_op("<");
- my $gt_op = infix_op(">");
- my $le_op = infix_op("<=");
- my $ge_op = infix_op(">=");
-
- #
- # XXX The standard perl PP code has extra handling for
- # some special case arguments of these operators.
- #
- sub pp_add { numeric_binop($_[0], $plus_op) }
- sub pp_subtract { numeric_binop($_[0], $minus_op) }
- sub pp_multiply { numeric_binop($_[0], $multiply_op) }
- sub pp_divide { numeric_binop($_[0], $divide_op) }
- sub pp_modulo { int_binop($_[0], $modulo_op) } # differs from perl's
-
- sub pp_left_shift { int_binop($_[0], $lshift_op) }
- sub pp_right_shift { int_binop($_[0], $rshift_op) }
- sub pp_i_add { int_binop($_[0], $plus_op) }
- sub pp_i_subtract { int_binop($_[0], $minus_op) }
- sub pp_i_multiply { int_binop($_[0], $multiply_op) }
- sub pp_i_divide { int_binop($_[0], $divide_op) }
- sub pp_i_modulo { int_binop($_[0], $modulo_op) }
-
- sub pp_eq { bool_numeric_binop($_[0], $eq_op) }
- sub pp_ne { bool_numeric_binop($_[0], $ne_op) }
- sub pp_lt { bool_numeric_binop($_[0], $lt_op) }
- sub pp_gt { bool_numeric_binop($_[0], $gt_op) }
- sub pp_le { bool_numeric_binop($_[0], $le_op) }
- sub pp_ge { bool_numeric_binop($_[0], $ge_op) }
-
- sub pp_i_eq { bool_int_binop($_[0], $eq_op) }
- sub pp_i_ne { bool_int_binop($_[0], $ne_op) }
- sub pp_i_lt { bool_int_binop($_[0], $lt_op) }
- sub pp_i_gt { bool_int_binop($_[0], $gt_op) }
- sub pp_i_le { bool_int_binop($_[0], $le_op) }
- sub pp_i_ge { bool_int_binop($_[0], $ge_op) }
-
- sub pp_scmp { sv_binop($_[0], $scmp_op, INT_RESULT) }
- sub pp_slt { bool_sv_binop($_[0], $slt_op) }
- sub pp_sgt { bool_sv_binop($_[0], $sgt_op) }
- sub pp_sle { bool_sv_binop($_[0], $sle_op) }
- sub pp_sge { bool_sv_binop($_[0], $sge_op) }
- sub pp_seq { bool_sv_binop($_[0], $seq_op) }
- sub pp_sne { bool_sv_binop($_[0], $sne_op) }
-}
-
-
-sub pp_sassign {
- my $op = shift;
- my $backwards = $op->private & OPpASSIGN_BACKWARDS;
- my ($dst, $src);
- if (@stack >= 2) {
- $dst = pop @stack;
- $src = pop @stack;
- ($src, $dst) = ($dst, $src) if $backwards;
- my $type = $src->{type};
- if ($type == T_INT) {
- $dst->set_int($src->as_int,$src->{flags} & VALID_UNSIGNED);
- } elsif ($type == T_DOUBLE) {
- $dst->set_numeric($src->as_numeric);
- } else {
- $dst->set_sv($src->as_sv);
- }
- push(@stack, $dst);
- } elsif (@stack == 1) {
- if ($backwards) {
- my $src = pop @stack;
- my $type = $src->{type};
- runtime("if (PL_tainting && PL_tainted) TAINT_NOT;");
- if ($type == T_INT) {
- if ($src->{flags} & VALID_UNSIGNED){
- runtime sprintf("sv_setuv(TOPs, %s);", $src->as_int);
- }else{
- runtime sprintf("sv_setiv(TOPs, %s);", $src->as_int);
- }
- } elsif ($type == T_DOUBLE) {
- runtime sprintf("sv_setnv(TOPs, %s);", $src->as_double);
- } else {
- runtime sprintf("sv_setsv(TOPs, %s);", $src->as_sv);
- }
- runtime("SvSETMAGIC(TOPs);");
- } else {
- my $dst = $stack[-1];
- my $type = $dst->{type};
- runtime("sv = POPs;");
- runtime("MAYBE_TAINT_SASSIGN_SRC(sv);");
- if ($type == T_INT) {
- $dst->set_int("SvIV(sv)");
- } elsif ($type == T_DOUBLE) {
- $dst->set_double("SvNV(sv)");
- } else {
- runtime("SvSetMagicSV($dst->{sv}, sv);");
- $dst->invalidate;
- }
- }
- } else {
- if ($backwards) {
- runtime("src = POPs; dst = TOPs;");
- } else {
- runtime("dst = POPs; src = TOPs;");
- }
- runtime("MAYBE_TAINT_SASSIGN_SRC(src);",
- "SvSetSV(dst, src);",
- "SvSETMAGIC(dst);",
- "SETs(dst);");
- }
- return $op->next;
-}
-
-sub pp_preinc {
- my $op = shift;
- if (@stack >= 1) {
- my $obj = $stack[-1];
- my $type = $obj->{type};
- if ($type == T_INT || $type == T_DOUBLE) {
- $obj->set_int($obj->as_int . " + 1");
- } else {
- runtime sprintf("PP_PREINC(%s);", $obj->as_sv);
- $obj->invalidate();
- }
- } else {
- runtime sprintf("PP_PREINC(TOPs);");
- }
- return $op->next;
-}
-
-
-sub pp_pushmark {
- my $op = shift;
- write_back_stack();
- runtime("PUSHMARK(sp);");
- return $op->next;
-}
-
-sub pp_list {
- my $op = shift;
- write_back_stack();
- my $gimme = gimme($op);
- if ($gimme == G_ARRAY) { # sic
- runtime("POPMARK;"); # need this even though not a "full" pp_list
- } else {
- runtime("PP_LIST($gimme);");
- }
- return $op->next;
-}
-
-sub pp_entersub {
- my $op = shift;
- $curcop->write_back;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- my $sym = doop($op);
- runtime("while (PL_op != ($sym)->op_next && PL_op != (OP*)0 ){");
- runtime("PL_op = (*PL_op->op_ppaddr)(aTHX);");
- runtime("SPAGAIN;}");
- $know_op = 0;
- invalidate_lexicals(REGISTER|TEMPORARY);
- return $op->next;
-}
-sub pp_formline {
- my $op = shift;
- my $ppname = $op->ppaddr;
- write_back_lexicals() unless $skip_lexicals{$ppname};
- write_back_stack() unless $skip_stack{$ppname};
- my $sym=doop($op);
- # See comment in pp_grepwhile to see why!
- $init->add("((LISTOP*)$sym)->op_first = $sym;");
- runtime("if (PL_op == ((LISTOP*)($sym))->op_first){");
- save_or_restore_lexical_state(${$op->first});
- runtime( sprintf("goto %s;",label($op->first)));
- runtime("}");
- return $op->next;
-}
-
-sub pp_goto{
-
- my $op = shift;
- my $ppname = $op->ppaddr;
- write_back_lexicals() unless $skip_lexicals{$ppname};
- write_back_stack() unless $skip_stack{$ppname};
- my $sym=doop($op);
- runtime("if (PL_op != ($sym)->op_next && PL_op != (OP*)0){return PL_op;}");
- invalidate_lexicals() unless $skip_invalidate{$ppname};
- return $op->next;
-}
-sub pp_enterwrite {
- my $op = shift;
- pp_entersub($op);
-}
-sub pp_leavesub{
- my $op = shift;
- write_back_lexicals() unless $skip_lexicals{$ppname};
- write_back_stack() unless $skip_stack{$ppname};
- runtime("if (PL_curstackinfo->si_type == PERLSI_SORT){");
- runtime("\tPUTBACK;return 0;");
- runtime("}");
- doop($op);
- return $op->next;
-}
-sub pp_leavewrite {
- my $op = shift;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- my $sym = doop($op);
- # XXX Is this the right way to distinguish between it returning
- # CvSTART(cv) (via doform) and pop_return()?
- #runtime("if (PL_op) PL_op = (*PL_op->op_ppaddr)(aTHX);");
- runtime("SPAGAIN;");
- $know_op = 0;
- invalidate_lexicals(REGISTER|TEMPORARY);
- return $op->next;
-}
-
-sub doeval {
- my $op = shift;
- $curcop->write_back;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- my $sym = loadop($op);
- my $ppaddr = $op->ppaddr;
- #runtime(qq/printf("$ppaddr type eval\n");/);
- runtime("PP_EVAL($ppaddr, ($sym)->op_next);");
- $know_op = 1;
- invalidate_lexicals(REGISTER|TEMPORARY);
- return $op->next;
-}
-
-sub pp_entereval { doeval(@_) }
-sub pp_dofile { doeval(@_) }
-
-#pp_require is protected by pp_entertry, so no protection for it.
-sub pp_require {
- my $op = shift;
- $curcop->write_back;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- my $sym = doop($op);
- runtime("while (PL_op != ($sym)->op_next && PL_op != (OP*)0 ){");
- runtime("PL_op = (*PL_op->op_ppaddr)(ARGS);");
- runtime("SPAGAIN;}");
- $know_op = 1;
- invalidate_lexicals(REGISTER|TEMPORARY);
- return $op->next;
-}
-
-
-sub pp_entertry {
- my $op = shift;
- $curcop->write_back;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- my $sym = doop($op);
- my $jmpbuf = sprintf("jmpbuf%d", $jmpbuf_ix++);
- declare("JMPENV", $jmpbuf);
- runtime(sprintf("PP_ENTERTRY(%s,%s);", $jmpbuf, label($op->other->next)));
- invalidate_lexicals(REGISTER|TEMPORARY);
- return $op->next;
-}
-
-sub pp_leavetry{
- my $op=shift;
- default_pp($op);
- runtime("PP_LEAVETRY;");
- return $op->next;
-}
-
-sub pp_grepstart {
- my $op = shift;
- if ($need_freetmps && $freetmps_each_loop) {
- runtime("FREETMPS;"); # otherwise the grepwhile loop messes things up
- $need_freetmps = 0;
- }
- write_back_stack();
- my $sym= doop($op);
- my $next=$op->next;
- $next->save;
- my $nexttonext=$next->next;
- $nexttonext->save;
- save_or_restore_lexical_state($$nexttonext);
- runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
- label($nexttonext)));
- return $op->next->other;
-}
-
-sub pp_mapstart {
- my $op = shift;
- if ($need_freetmps && $freetmps_each_loop) {
- runtime("FREETMPS;"); # otherwise the mapwhile loop messes things up
- $need_freetmps = 0;
- }
- write_back_stack();
- # pp_mapstart can return either op_next->op_next or op_next->op_other and
- # we need to be able to distinguish the two at runtime.
- my $sym= doop($op);
- my $next=$op->next;
- $next->save;
- my $nexttonext=$next->next;
- $nexttonext->save;
- save_or_restore_lexical_state($$nexttonext);
- runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
- label($nexttonext)));
- return $op->next->other;
-}
-
-sub pp_grepwhile {
- my $op = shift;
- my $next = $op->next;
- unshift(@bblock_todo, $next);
- write_back_lexicals();
- write_back_stack();
- my $sym = doop($op);
- # pp_grepwhile can return either op_next or op_other and we need to
- # be able to distinguish the two at runtime. Since it's possible for
- # both ops to be "inlined", the fields could both be zero. To get
- # around that, we hack op_next to be our own op (purely because we
- # know it's a non-NULL pointer and can't be the same as op_other).
- $init->add("((LOGOP*)$sym)->op_next = $sym;");
- save_or_restore_lexical_state($$next);
- runtime(sprintf("if (PL_op == ($sym)->op_next) goto %s;", label($next)));
- $know_op = 0;
- return $op->other;
-}
-
-sub pp_mapwhile {
- pp_grepwhile(@_);
-}
-
-sub pp_return {
- my $op = shift;
- write_back_lexicals(REGISTER|TEMPORARY);
- write_back_stack();
- doop($op);
- runtime("PUTBACK;", "return PL_op;");
- $know_op = 0;
- return $op->next;
-}
-
-sub nyi {
- my $op = shift;
- warn sprintf("%s not yet implemented properly\n", $op->ppaddr);
- return default_pp($op);
-}
-
-sub pp_range {
- my $op = shift;
- my $flags = $op->flags;
- if (!($flags & OPf_WANT)) {
- error("context of range unknown at compile-time");
- }
- write_back_lexicals();
- write_back_stack();
- unless (($flags & OPf_WANT)== OPf_WANT_LIST) {
- # We need to save our UNOP structure since pp_flop uses
- # it to find and adjust out targ. We don't need it ourselves.
- $op->save;
- save_or_restore_lexical_state(${$op->other});
- runtime sprintf("if (SvTRUE(PL_curpad[%d])) goto %s;",
- $op->targ, label($op->other));
- unshift(@bblock_todo, $op->other);
- }
- return $op->next;
-}
-
-sub pp_flip {
- my $op = shift;
- my $flags = $op->flags;
- if (!($flags & OPf_WANT)) {
- error("context of flip unknown at compile-time");
- }
- if (($flags & OPf_WANT)==OPf_WANT_LIST) {
- return $op->first->other;
- }
- write_back_lexicals();
- write_back_stack();
- # We need to save our UNOP structure since pp_flop uses
- # it to find and adjust out targ. We don't need it ourselves.
- $op->save;
- my $ix = $op->targ;
- my $rangeix = $op->first->targ;
- runtime(($op->private & OPpFLIP_LINENUM) ?
- "if (PL_last_in_gv && SvIV(TOPs) == IoLINES(GvIOp(PL_last_in_gv))) {"
- : "if (SvTRUE(TOPs)) {");
- runtime("\tsv_setiv(PL_curpad[$rangeix], 1);");
- if ($op->flags & OPf_SPECIAL) {
- runtime("sv_setiv(PL_curpad[$ix], 1);");
- } else {
- save_or_restore_lexical_state(${$op->first->other});
- runtime("\tsv_setiv(PL_curpad[$ix], 0);",
- "\tsp--;",
- sprintf("\tgoto %s;", label($op->first->other)));
- }
- runtime("}",
- qq{sv_setpv(PL_curpad[$ix], "");},
- "SETs(PL_curpad[$ix]);");
- $know_op = 0;
- return $op->next;
-}
-
-sub pp_flop {
- my $op = shift;
- default_pp($op);
- $know_op = 0;
- return $op->next;
-}
-
-sub enterloop {
- my $op = shift;
- my $nextop = $op->nextop;
- my $lastop = $op->lastop;
- my $redoop = $op->redoop;
- $curcop->write_back;
- debug "enterloop: pushing on cxstack" if $debug_cxstack;
- push(@cxstack, {
- type => CXt_LOOP,
- op => $op,
- "label" => $curcop->[0]->label,
- nextop => $nextop,
- lastop => $lastop,
- redoop => $redoop
- });
- $nextop->save;
- $lastop->save;
- $redoop->save;
- return default_pp($op);
-}
-
-sub pp_enterloop { enterloop(@_) }
-sub pp_enteriter { enterloop(@_) }
-
-sub pp_leaveloop {
- my $op = shift;
- if (!@cxstack) {
- die "panic: leaveloop";
- }
- debug "leaveloop: popping from cxstack" if $debug_cxstack;
- pop(@cxstack);
- return default_pp($op);
-}
-
-sub pp_next {
- my $op = shift;
- my $cxix;
- if ($op->flags & OPf_SPECIAL) {
- $cxix = dopoptoloop();
- if ($cxix < 0) {
- error('"next" used outside loop');
- return $op->next; # ignore the op
- }
- } else {
- $cxix = dopoptolabel($op->pv);
- if ($cxix < 0) {
- error('Label not found at compile time for "next %s"', $op->pv);
- return $op->next; # ignore the op
- }
- }
- default_pp($op);
- my $nextop = $cxstack[$cxix]->{nextop};
- push(@bblock_todo, $nextop);
- save_or_restore_lexical_state($$nextop);
- runtime(sprintf("goto %s;", label($nextop)));
- return $op->next;
-}
-
-sub pp_redo {
- my $op = shift;
- my $cxix;
- if ($op->flags & OPf_SPECIAL) {
- $cxix = dopoptoloop();
- if ($cxix < 0) {
- error('"redo" used outside loop');
- return $op->next; # ignore the op
- }
- } else {
- $cxix = dopoptolabel($op->pv);
- if ($cxix < 0) {
- error('Label not found at compile time for "redo %s"', $op->pv);
- return $op->next; # ignore the op
- }
- }
- default_pp($op);
- my $redoop = $cxstack[$cxix]->{redoop};
- push(@bblock_todo, $redoop);
- save_or_restore_lexical_state($$redoop);
- runtime(sprintf("goto %s;", label($redoop)));
- return $op->next;
-}
-
-sub pp_last {
- my $op = shift;
- my $cxix;
- if ($op->flags & OPf_SPECIAL) {
- $cxix = dopoptoloop();
- if ($cxix < 0) {
- error('"last" used outside loop');
- return $op->next; # ignore the op
- }
- } else {
- $cxix = dopoptolabel($op->pv);
- if ($cxix < 0) {
- error('Label not found at compile time for "last %s"', $op->pv);
- return $op->next; # ignore the op
- }
- # XXX Add support for "last" to leave non-loop blocks
- if ($cxstack[$cxix]->{type} != CXt_LOOP) {
- error('Use of "last" for non-loop blocks is not yet implemented');
- return $op->next; # ignore the op
- }
- }
- default_pp($op);
- my $lastop = $cxstack[$cxix]->{lastop}->next;
- push(@bblock_todo, $lastop);
- save_or_restore_lexical_state($$lastop);
- runtime(sprintf("goto %s;", label($lastop)));
- return $op->next;
-}
-
-sub pp_subst {
- my $op = shift;
- write_back_lexicals();
- write_back_stack();
- my $sym = doop($op);
- my $replroot = $op->pmreplroot;
- if ($$replroot) {
- save_or_restore_lexical_state($$replroot);
- runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplroot) goto %s;",
- $sym, label($replroot));
- $op->pmreplstart->save;
- push(@bblock_todo, $replroot);
- }
- invalidate_lexicals();
- return $op->next;
-}
-
-sub pp_substcont {
- my $op = shift;
- write_back_lexicals();
- write_back_stack();
- doop($op);
- my $pmop = $op->other;
- # warn sprintf("substcont: op = %s, pmop = %s\n",
- # peekop($op), peekop($pmop));#debug
-# my $pmopsym = objsym($pmop);
- my $pmopsym = $pmop->save; # XXX can this recurse?
-# warn "pmopsym = $pmopsym\n";#debug
- save_or_restore_lexical_state(${$pmop->pmreplstart});
- runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplstart) goto %s;",
- $pmopsym, label($pmop->pmreplstart));
- invalidate_lexicals();
- return $pmop->next;
-}
-
-sub default_pp {
- my $op = shift;
- my $ppname = "pp_" . $op->name;
- if ($curcop and $need_curcop{$ppname}){
- $curcop->write_back;
- }
- write_back_lexicals() unless $skip_lexicals{$ppname};
- write_back_stack() unless $skip_stack{$ppname};
- doop($op);
- # XXX If the only way that ops can write to a TEMPORARY lexical is
- # when it's named in $op->targ then we could call
- # invalidate_lexicals(TEMPORARY) and avoid having to write back all
- # the temporaries. For now, we'll play it safe and write back the lot.
- invalidate_lexicals() unless $skip_invalidate{$ppname};
- return $op->next;
-}
-
-sub compile_op {
- my $op = shift;
- my $ppname = "pp_" . $op->name;
- if (exists $ignore_op{$ppname}) {
- return $op->next;
- }
- debug peek_stack() if $debug_stack;
- if ($debug_op) {
- debug sprintf("%s [%s]\n",
- peekop($op),
- $op->flags & OPf_STACKED ? "OPf_STACKED" : $op->targ);
- }
- no strict 'refs';
- if (defined(&$ppname)) {
- $know_op = 0;
- return &$ppname($op);
- } else {
- return default_pp($op);
- }
-}
-
-sub compile_bblock {
- my $op = shift;
- #warn "compile_bblock: ", peekop($op), "\n"; # debug
- save_or_restore_lexical_state($$op);
- write_label($op);
- $know_op = 0;
- do {
- $op = compile_op($op);
- } while (defined($op) && $$op && !exists($leaders->{$$op}));
- write_back_stack(); # boo hoo: big loss
- reload_lexicals();
- return $op;
-}
-
-sub cc {
- my ($name, $root, $start, @padlist) = @_;
- my $op;
- if($done{$$start}){
- #warn "repeat=>".ref($start)."$name,\n";#debug
- $decl->add(sprintf("#define $name %s",$done{$$start}));
- return;
- }
- init_pp($name);
- load_pad(@padlist);
- %lexstate=();
- B::Pseudoreg->new_scope;
- @cxstack = ();
- if ($debug_timings) {
- warn sprintf("Basic block analysis at %s\n", timing_info);
- }
- $leaders = find_leaders($root, $start);
- my @leaders= keys %$leaders;
- if ($#leaders > -1) {
- @bblock_todo = ($start, values %$leaders) ;
- } else{
- runtime("return PL_op?PL_op->op_next:0;");
- }
- if ($debug_timings) {
- warn sprintf("Compilation at %s\n", timing_info);
- }
- while (@bblock_todo) {
- $op = shift @bblock_todo;
- #warn sprintf("Considering basic block %s\n", peekop($op)); # debug
- next if !defined($op) || !$$op || $done{$$op};
- #warn "...compiling it\n"; # debug
- do {
- $done{$$op} = $name;
- $op = compile_bblock($op);
- if ($need_freetmps && $freetmps_each_bblock) {
- runtime("FREETMPS;");
- $need_freetmps = 0;
- }
- } while defined($op) && $$op && !$done{$$op};
- if ($need_freetmps && $freetmps_each_loop) {
- runtime("FREETMPS;");
- $need_freetmps = 0;
- }
- if (!$$op) {
- runtime("PUTBACK;","return PL_op;");
- } elsif ($done{$$op}) {
- save_or_restore_lexical_state($$op);
- runtime(sprintf("goto %s;", label($op)));
- }
- }
- if ($debug_timings) {
- warn sprintf("Saving runtime at %s\n", timing_info);
- }
- declare_pad(@padlist) ;
- save_runtime();
-}
-
-sub cc_recurse {
- my $ccinfo;
- my $start;
- $start = cc_queue(@_) if @_;
- while ($ccinfo = shift @cc_todo) {
- cc(@$ccinfo);
- }
- return $start;
-}
-
-sub cc_obj {
- my ($name, $cvref) = @_;
- my $cv = svref_2object($cvref);
- my @padlist = $cv->PADLIST->ARRAY;
- my $curpad_sym = $padlist[1]->save;
- cc_recurse($name, $cv->ROOT, $cv->START, @padlist);
-}
-
-sub cc_main {
- my @comppadlist = comppadlist->ARRAY;
- my $curpad_nam = $comppadlist[0]->save;
- my $curpad_sym = $comppadlist[1]->save;
- my $init_av = init_av->save;
- my $start = cc_recurse("pp_main", main_root, main_start, @comppadlist);
- # Do save_unused_subs before saving inc_hv
- save_unused_subs();
- cc_recurse();
-
- my $inc_hv = svref_2object(\%INC)->save;
- my $inc_av = svref_2object(\@INC)->save;
- my $amagic_generate= amagic_generation;
- return if $errors;
- if (!defined($module)) {
- $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
- "PL_main_start = $start;",
- "PL_curpad = AvARRAY($curpad_sym);",
- "PL_initav = (AV *) $init_av;",
- "GvHV(PL_incgv) = $inc_hv;",
- "GvAV(PL_incgv) = $inc_av;",
- "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
- "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
- "PL_amagic_generation= $amagic_generate;",
- );
-
- }
- seek(STDOUT,0,0); #prevent print statements from BEGIN{} into the output
- output_boilerplate();
- print "\n";
- output_all("perl_init");
- output_runtime();
- print "\n";
- output_main();
- if (defined($module)) {
- my $cmodule = $module;
- $cmodule =~ s/::/__/g;
- print <<"EOT";
-
-#include "XSUB.h"
-XS(boot_$cmodule)
-{
- dXSARGS;
- perl_init();
- ENTER;
- SAVETMPS;
- SAVEVPTR(PL_curpad);
- SAVEVPTR(PL_op);
- PL_curpad = AvARRAY($curpad_sym);
- PL_op = $start;
- pp_main(aTHX);
- FREETMPS;
- LEAVE;
- ST(0) = &PL_sv_yes;
- XSRETURN(1);
-}
-EOT
- }
- if ($debug_timings) {
- warn sprintf("Done at %s\n", timing_info);
- }
-}
-
-sub compile {
- my @options = @_;
- my ($option, $opt, $arg);
- OPTION:
- while ($option = shift @options) {
- if ($option =~ /^-(.)(.*)/) {
- $opt = $1;
- $arg = $2;
- } else {
- unshift @options, $option;
- last OPTION;
- }
- if ($opt eq "-" && $arg eq "-") {
- shift @options;
- last OPTION;
- } elsif ($opt eq "o") {
- $arg ||= shift @options;
- open(STDOUT, ">$arg") or return "open '>$arg': $!\n";
- } elsif ($opt eq "n") {
- $arg ||= shift @options;
- $module_name = $arg;
- } elsif ($opt eq "u") {
- $arg ||= shift @options;
- mark_unused($arg,undef);
- } elsif ($opt eq "f") {
- $arg ||= shift @options;
- my $value = $arg !~ s/^no-//;
- $arg =~ s/-/_/g;
- my $ref = $optimise{$arg};
- if (defined($ref)) {
- $$ref = $value;
- } else {
- warn qq(ignoring unknown optimisation option "$arg"\n);
- }
- } elsif ($opt eq "O") {
- $arg = 1 if $arg eq "";
- my $ref;
- foreach $ref (values %optimise) {
- $$ref = 0;
- }
- if ($arg >= 2) {
- $freetmps_each_loop = 1;
- }
- if ($arg >= 1) {
- $freetmps_each_bblock = 1 unless $freetmps_each_loop;
- }
- } elsif ($opt eq "m") {
- $arg ||= shift @options;
- $module = $arg;
- mark_unused($arg,undef);
- } elsif ($opt eq "p") {
- $arg ||= shift @options;
- $patchlevel = $arg;
- } elsif ($opt eq "D") {
- $arg ||= shift @options;
- foreach $arg (split(//, $arg)) {
- if ($arg eq "o") {
- B->debug(1);
- } elsif ($arg eq "O") {
- $debug_op = 1;
- } elsif ($arg eq "s") {
- $debug_stack = 1;
- } elsif ($arg eq "c") {
- $debug_cxstack = 1;
- } elsif ($arg eq "p") {
- $debug_pad = 1;
- } elsif ($arg eq "r") {
- $debug_runtime = 1;
- } elsif ($arg eq "S") {
- $debug_shadow = 1;
- } elsif ($arg eq "q") {
- $debug_queue = 1;
- } elsif ($arg eq "l") {
- $debug_lineno = 1;
- } elsif ($arg eq "t") {
- $debug_timings = 1;
- }
- }
- }
- }
- init_sections();
- $init = B::Section->get("init");
- $decl = B::Section->get("decl");
-
- if (@options) {
- return sub {
- my ($objname, $ppname);
- foreach $objname (@options) {
- $objname = "main::$objname" unless $objname =~ /::/;
- ($ppname = $objname) =~ s/^.*?:://;
- eval "cc_obj(qq(pp_sub_$ppname), \\&$objname)";
- die "cc_obj(qq(pp_sub_$ppname, \\&$objname) failed: $@" if $@;
- return if $errors;
- }
- output_boilerplate();
- print "\n";
- output_all($module_name || "init_module");
- output_runtime();
- }
- } else {
- return sub { cc_main() };
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::CC - Perl compiler's optimized C translation backend
-
-=head1 SYNOPSIS
-
- perl -MO=CC[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This compiler backend takes Perl source and generates C source code
-corresponding to the flow of your program. In other words, this
-backend is somewhat a "real" compiler in the sense that many people
-think about compilers. Note however that, currently, it is a very
-poor compiler in that although it generates (mostly, or at least
-sometimes) correct code, it performs relatively few optimisations.
-This will change as the compiler develops. The result is that
-running an executable compiled with this backend may start up more
-quickly than running the original Perl program (a feature shared
-by the B<C> compiler backend--see F<B::C>) and may also execute
-slightly faster. This is by no means a good optimising compiler--yet.
-
-=head1 OPTIONS
-
-If there are any non-option arguments, they are taken to be
-names of objects to be saved (probably doesn't work properly yet).
-Without extra arguments, it saves the main program.
-
-=over 4
-
-=item B<-ofilename>
-
-Output to filename instead of STDOUT
-
-=item B<-v>
-
-Verbose compilation (currently gives a few compilation statistics).
-
-=item B<-->
-
-Force end of options
-
-=item B<-uPackname>
-
-Force apparently unused subs from package Packname to be compiled.
-This allows programs to use eval "foo()" even when sub foo is never
-seen to be used at compile time. The down side is that any subs which
-really are never used also have code generated. This option is
-necessary, for example, if you have a signal handler foo which you
-initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
-to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
-options. The compiler tries to figure out which packages may possibly
-have subs in which need compiling but the current version doesn't do
-it very well. In particular, it is confused by nested packages (i.e.
-of the form C<A::B>) where package C<A> does not contain any subs.
-
-=item B<-mModulename>
-
-Instead of generating source for a runnable executable, generate
-source for an XSUB module. The boot_Modulename function (which
-DynaLoader can look for) does the appropriate initialisation and runs
-the main part of the Perl source that is being compiled.
-
-
-=item B<-D>
-
-Debug options (concatenated or separate flags like C<perl -D>).
-
-=item B<-Dr>
-
-Writes debugging output to STDERR just as it's about to write to the
-program's runtime (otherwise writes debugging info as comments in
-its C output).
-
-=item B<-DO>
-
-Outputs each OP as it's compiled
-
-=item B<-Ds>
-
-Outputs the contents of the shadow stack at each OP
-
-=item B<-Dp>
-
-Outputs the contents of the shadow pad of lexicals as it's loaded for
-each sub or the main program.
-
-=item B<-Dq>
-
-Outputs the name of each fake PP function in the queue as it's about
-to process it.
-
-=item B<-Dl>
-
-Output the filename and line number of each original line of Perl
-code as it's processed (C<pp_nextstate>).
-
-=item B<-Dt>
-
-Outputs timing information of compilation stages.
-
-=item B<-f>
-
-Force optimisations on or off one at a time.
-
-=item B<-ffreetmps-each-bblock>
-
-Delays FREETMPS from the end of each statement to the end of the each
-basic block.
-
-=item B<-ffreetmps-each-loop>
-
-Delays FREETMPS from the end of each statement to the end of the group
-of basic blocks forming a loop. At most one of the freetmps-each-*
-options can be used.
-
-=item B<-fomit-taint>
-
-Omits generating code for handling perl's tainting mechanism.
-
-=item B<-On>
-
-Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>.
-Currently, B<-O1> sets B<-ffreetmps-each-bblock> and B<-O2>
-sets B<-ffreetmps-each-loop>.
-
-=back
-
-=head1 EXAMPLES
-
- perl -MO=CC,-O2,-ofoo.c foo.pl
- perl cc_harness -o foo foo.c
-
-Note that C<cc_harness> lives in the C<B> subdirectory of your perl
-library directory. The utility called C<perlcc> may also be used to
-help make use of this compiler.
-
- perl -MO=CC,-mFoo,-oFoo.c Foo.pm
- perl cc_harness -shared -c -o Foo.so Foo.c
-
-=head1 BUGS
-
-Plenty. Current status: experimental.
-
-=head1 DIFFERENCES
-
-These aren't really bugs but they are constructs which are heavily
-tied to perl's compile-and-go implementation and with which this
-compiler backend cannot cope.
-
-=head2 Loops
-
-Standard perl calculates the target of "next", "last", and "redo"
-at run-time. The compiler calculates the targets at compile-time.
-For example, the program
-
- sub skip_on_odd { next NUMBER if $_[0] % 2 }
- NUMBER: for ($i = 0; $i < 5; $i++) {
- skip_on_odd($i);
- print $i;
- }
-
-produces the output
-
- 024
-
-with standard perl but gives a compile-time error with the compiler.
-
-=head2 Context of ".."
-
-The context (scalar or array) of the ".." operator determines whether
-it behaves as a range or a flip/flop. Standard perl delays until
-runtime the decision of which context it is in but the compiler needs
-to know the context at compile-time. For example,
-
- @a = (4,6,1,0,0,1);
- sub range { (shift @a)..(shift @a) }
- print range();
- while (@a) { print scalar(range()) }
-
-generates the output
-
- 456123E0
-
-with standard Perl but gives a compile-time error with compiled Perl.
-
-=head2 Arithmetic
-
-Compiled Perl programs use native C arithemtic much more frequently
-than standard perl. Operations on large numbers or on boundary
-cases may produce different behaviour.
-
-=head2 Deprecated features
-
-Features of standard perl such as C<$[> which have been deprecated
-in standard perl since Perl5 was released have not been implemented
-in the compiler.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Concise.pm b/contrib/perl5/ext/B/B/Concise.pm
deleted file mode 100644
index cb352eb..0000000
--- a/contrib/perl5/ext/B/B/Concise.pm
+++ /dev/null
@@ -1,823 +0,0 @@
-package B::Concise;
-# Copyright (C) 2000, 2001 Stephen McCamant. All rights reserved.
-# This program is free software; you can redistribute and/or modify it
-# under the same terms as Perl itself.
-
-our $VERSION = "0.51";
-use strict;
-use B qw(class ppname main_start main_root main_cv cstring svref_2object
- SVf_IOK SVf_NOK SVf_POK OPf_KIDS);
-
-my %style =
- ("terse" =>
- ["(?(#label =>\n)?)(*( )*)#class (#addr) #name (?([#targ])?) "
- . "#svclass~(?((#svaddr))?)~#svval~(?(label \"#coplabel\")?)\n",
- "(*( )*)goto #class (#addr)\n",
- "#class pp_#name"],
- "concise" =>
- ["#hyphseq2 (*( (x( ;)x))*)<#classsym> "
- . "#exname#arg(?([#targarglife])?)~#flags(?(/#private)?)(x(;~->#next)x)\n",
- " (*( )*) goto #seq\n",
- "(?(<#seq>)?)#exname#arg(?([#targarglife])?)"],
- "linenoise" =>
- ["(x(;(*( )*))x)#noise#arg(?([#targarg])?)(x( ;\n)x)",
- "gt_#seq ",
- "(?(#seq)?)#noise#arg(?([#targarg])?)"],
- "debug" =>
- ["#class (#addr)\n\top_next\t\t#nextaddr\n\top_sibling\t#sibaddr\n\t"
- . "op_ppaddr\tPL_ppaddr[OP_#NAME]\n\top_type\t\t#typenum\n\top_seq\t\t"
- . "#seqnum\n\top_flags\t#flagval\n\top_private\t#privval\n"
- . "(?(\top_first\t#firstaddr\n)?)(?(\top_last\t\t#lastaddr\n)?)"
- . "(?(\top_sv\t\t#svaddr\n)?)",
- " GOTO #addr\n",
- "#addr"],
- "env" => [$ENV{B_CONCISE_FORMAT}, $ENV{B_CONCISE_GOTO_FORMAT},
- $ENV{B_CONCISE_TREE_FORMAT}],
- );
-
-my($format, $gotofmt, $treefmt);
-my $curcv;
-my($seq_base, $cop_seq_base);
-
-sub concise_cv {
- my ($order, $cvref) = @_;
- my $cv = svref_2object($cvref);
- $curcv = $cv;
- 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)
- }
-}
-
-my $start_sym = "\e(0"; # "\cN" sometimes also works
-my $end_sym = "\e(B"; # "\cO" respectively
-
-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";
-
-sub compile {
- my @options = grep(/^-/, @_);
- my @args = grep(!/^-/, @_);
- my $do_main = 0;
- ($format, $gotofmt, $treefmt) = @{$style{"concise"}};
- for my $o (@options) {
- if ($o eq "-basic") {
- $order = "basic";
- } elsif ($o eq "-exec") {
- $order = "exec";
- } elsif ($o eq "-tree") {
- $order = "tree";
- } elsif ($o eq "-compact") {
- $tree_style |= 1;
- } elsif ($o eq "-loose") {
- $tree_style &= ~1;
- } elsif ($o eq "-vt") {
- $tree_style |= 2;
- } elsif ($o eq "-ascii") {
- $tree_style &= ~2;
- } elsif ($o eq "-main") {
- $do_main = 1;
- } elsif ($o =~ /^-base(\d+)$/) {
- $base = $1;
- } elsif ($o eq "-bigendian") {
- $big_endian = 1;
- } elsif ($o eq "-littleendian") {
- $big_endian = 0;
- } elsif (exists $style{substr($o, 1)}) {
- ($format, $gotofmt, $treefmt) = @{$style{substr($o, 1)}};
- } else {
- warn "Option $o unrecognized";
- }
- }
- if (@args) {
- return sub {
- for my $objname (@args) {
- $objname = "main::" . $objname unless $objname =~ /::/;
- eval "concise_cv(\$order, \\&$objname)";
- die "concise_cv($order, \\&$objname) failed: $@" if $@;
- }
- }
- }
- if (!@args or $do_main) {
- if ($order eq "exec") {
- return sub { return if class(main_start) eq "NULL";
- $curcv = main_cv;
- walk_exec(main_start) }
- } elsif ($order eq "tree") {
- return sub { return if class(main_root) eq "NULL";
- $curcv = main_cv;
- print tree(main_root, 0) }
- } elsif ($order eq "basic") {
- return sub { return if class(main_root) eq "NULL";
- $curcv = main_cv;
- walk_topdown(main_root,
- sub { $_[0]->concise($_[1]) }, 0); }
- }
- }
-}
-
-my %labels;
-my $lastnext;
-
-my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
- 'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
- 'PVOP' => '"', 'LOOP' => "{", 'COP' => ";");
-
-my @linenoise =
- qw'# () sc ( @? 1 $* gv *{ m$ m@ m% m? p/ *$ $ $# & a& pt \\ s\\ rf bl
- ` *? <> ?? ?/ r/ c/ // qr s/ /c y/ = @= C sC Cp sp df un BM po +1 +I
- -1 -I 1+ I+ 1- I- ** * i* / i/ %$ i% x + i+ - i- . " << >> < i<
- > i> <= i, >= i. == i= != i! <? i? s< s> s, s. s= s! s? b& b^ b| -0 -i
- ! ~ a2 si cs rd sr e^ lg sq in %x %o ab le ss ve ix ri sf FL od ch cy
- uf lf uc lc qm @ [f [ @[ eh vl ky dl ex % ${ @{ uk pk st jn ) )[ a@
- a% sl +] -] [- [+ so rv GS GW MS MW .. f. .f && || ^^ ?: &= |= -> s{ s}
- v} ca wa di rs ;; ; ;d }{ { } {} f{ it {l l} rt }l }n }r dm }g }e ^o
- ^c ^| ^# um bm t~ u~ ~d DB db ^s se ^g ^r {w }w pf pr ^O ^K ^R ^W ^d ^v
- ^e ^t ^k t. fc ic fl .s .p .b .c .l .a .h g1 s1 g2 s2 ?. l? -R -W -X -r
- -w -x -e -o -O -z -s -M -A -C -S -c -b -f -d -p -l -u -g -k -t -T -B cd
- co cr u. cm ut r. l@ s@ r@ mD uD oD rD tD sD wD cD f$ w$ p$ sh e$ k$ g3
- g4 s4 g5 s5 T@ C@ L@ G@ A@ S@ Hg Hc Hr Hw Mg Mc Ms Mr Sg Sc So rq do {e
- e} {t t} g6 G6 6e g7 G7 7e g8 G8 8e g9 G9 9e 6s 7s 8s 9s 6E 7E 8E 9E Pn
- Pu GP SP EP Gn Gg GG SG EG g0 c$ lk t$ ;s n>';
-
-my $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-sub op_flags {
- my($x) = @_;
- my(@v);
- push @v, "v" if ($x & 3) == 1;
- push @v, "s" if ($x & 3) == 2;
- push @v, "l" if ($x & 3) == 3;
- push @v, "K" if $x & 4;
- push @v, "P" if $x & 8;
- push @v, "R" if $x & 16;
- push @v, "M" if $x & 32;
- push @v, "S" if $x & 64;
- push @v, "*" if $x & 128;
- return join("", @v);
-}
-
-sub base_n {
- my $x = shift;
- return "-" . base_n(-$x) if $x < 0;
- my $str = "";
- do { $str .= substr($chars, $x % $base, 1) } while $x = int($x / $base);
- $str = reverse $str if $big_endian;
- return $str;
-}
-
-sub seq { return $_[0]->seq ? base_n($_[0]->seq - $seq_base) : "-" }
-
-sub walk_topdown {
- my($op, $sub, $level) = @_;
- $sub->($op, $level);
- if ($op->flags & OPf_KIDS) {
- for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
- walk_topdown($kid, $sub, $level + 1);
- }
- }
- if (class($op) eq "PMOP" and $ {$op->pmreplroot}
- and $op->pmreplroot->isa("B::OP")) {
- walk_topdown($op->pmreplroot, $sub, $level + 1);
- }
-}
-
-sub walklines {
- my($ar, $level) = @_;
- for my $l (@$ar) {
- if (ref($l) eq "ARRAY") {
- walklines($l, $level + 1);
- } else {
- $l->concise($level);
- }
- }
-}
-
-sub walk_exec {
- my($top, $level) = @_;
- my %opsseen;
- my @lines;
- my @todo = ([$top, \@lines]);
- while (@todo and my($op, $targ) = @{shift @todo}) {
- for (; $$op; $op = $op->next) {
- last if $opsseen{$$op}++;
- push @$targ, $op;
- my $name = $op->name;
- if ($name
- =~ /^(or|and|(map|grep)while|entertry|range|cond_expr)$/) {
- my $ar = [];
- push @$targ, $ar;
- push @todo, [$op->other, $ar];
- } elsif ($name eq "subst" and $ {$op->pmreplstart}) {
- my $ar = [];
- push @$targ, $ar;
- push @todo, [$op->pmreplstart, $ar];
- } elsif ($name =~ /^enter(loop|iter)$/) {
- $labels{$op->nextop->seq} = "NEXT";
- $labels{$op->lastop->seq} = "LAST";
- $labels{$op->redoop->seq} = "REDO";
- }
- }
- }
- walklines(\@lines, 0);
-}
-
-sub fmt_line {
- my($hr, $fmt, $level) = @_;
- my $text = $fmt;
- $text =~ s/\(\?\(([^\#]*?)\#(\w+)([^\#]*?)\)\?\)/
- $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/[ \t]*~+[ \t]*/ /g;
- return $text;
-}
-
-my %priv;
-$priv{$_}{128} = "LVINTRO"
- for ("pos", "substr", "vec", "threadsv", "gvsv", "rv2sv", "rv2hv", "rv2gv",
- "rv2av", "rv2arylen", "aelem", "helem", "aslice", "hslice", "padsv",
- "padav", "padhv");
-$priv{$_}{64} = "REFC" for ("leave", "leavesub", "leavesublv", "leavewrite");
-$priv{"aassign"}{64} = "COMMON";
-$priv{"aassign"}{32} = "PHASH";
-$priv{"sassign"}{64} = "BKWARD";
-$priv{$_}{64} = "RTIME" for ("match", "subst", "substcont");
-@{$priv{"trans"}}{1,2,4,8,16,64} = ("<UTF", ">UTF", "IDENT", "SQUASH", "DEL",
- "COMPL", "GROWS");
-$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");
-$priv{"entersub"}{16} = "DBG";
-$priv{"entersub"}{32} = "TARG";
-@{$priv{$_}}{4,8,128} = ("INARGS","AMPER","NO()") for ("entersub", "rv2cv");
-$priv{"gv"}{32} = "EARLYCV";
-$priv{"aelem"}{16} = $priv{"helem"}{16} = "LVDEFER";
-$priv{$_}{16} = "OURINTR" for ("gvsv", "rv2sv", "rv2av", "rv2hv", "r2gv");
-$priv{$_}{16} = "TARGMY"
- for (map(($_,"s$_"),"chop", "chomp"),
- map(($_,"i_$_"), "postinc", "postdec", "multiply", "divide", "modulo",
- "add", "subtract", "negate"), "pow", "concat", "stringify",
- "left_shift", "right_shift", "bit_and", "bit_xor", "bit_or",
- "complement", "atan2", "sin", "cos", "rand", "exp", "log", "sqrt",
- "int", "hex", "oct", "abs", "length", "index", "rindex", "sprintf",
- "ord", "chr", "crypt", "quotemeta", "join", "push", "unshift", "flock",
- "chdir", "chown", "chroot", "unlink", "chmod", "utime", "rename",
- "link", "symlink", "mkdir", "rmdir", "wait", "waitpid", "system",
- "exec", "kill", "getppid", "getpgrp", "setpgrp", "getpriority",
- "setpriority", "time", "sleep");
-@{$priv{"const"}}{8,16,32,64,128} = ("STRICT","ENTERED", "$[", "BARE", "WARN");
-$priv{"flip"}{64} = $priv{"flop"}{64} = "LINENUM";
-$priv{"list"}{64} = "GUESSED";
-$priv{"delete"}{64} = "SLICE";
-$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{"threadsv"}{64} = "SVREFd";
-$priv{$_}{16} = "INBIN" for ("open", "backtick");
-$priv{$_}{32} = "INCR" for ("open", "backtick");
-$priv{$_}{64} = "OUTBIN" for ("open", "backtick");
-$priv{$_}{128} = "OUTCR" for ("open", "backtick");
-$priv{"exit"}{128} = "VMS";
-
-sub private_flags {
- my($name, $x) = @_;
- my @s;
- for my $flag (128, 96, 64, 32, 16, 8, 4, 2, 1) {
- if ($priv{$name}{$flag} and $x & $flag and $x >= $flag) {
- $x -= $flag;
- push @s, $priv{$name}{$flag};
- }
- }
- push @s, $x if $x;
- return join(",", @s);
-}
-
-sub concise_op {
- my ($op, $level, $format) = @_;
- my %h;
- $h{exname} = $h{name} = $op->name;
- $h{NAME} = uc $h{name};
- $h{class} = class($op);
- $h{extarg} = $h{targ} = $op->targ;
- $h{extarg} = "" unless $h{extarg};
- if ($h{name} eq "null" and $h{targ}) {
- $h{exname} = "ex-" . substr(ppname($h{targ}), 3);
- $h{extarg} = "";
- } elsif ($h{targ}) {
- my $padname = (($curcv->PADLIST->ARRAY)[0]->ARRAY)[$h{targ}];
- if (defined $padname and class($padname) ne "SPECIAL") {
- $h{targarg} = $padname->PVX;
- my $intro = $padname->NVX - $cop_seq_base;
- my $finish = int($padname->IVX) - $cop_seq_base;
- $finish = "end" if $finish == 999999999 - $cop_seq_base;
- $h{targarglife} = "$h{targarg}:$intro,$finish";
- } else {
- $h{targarglife} = $h{targarg} = "t" . $h{targ};
- }
- }
- $h{arg} = "";
- $h{svclass} = $h{svaddr} = $h{svval} = "";
- if ($h{class} eq "PMOP") {
- my $precomp = $op->precomp;
- $precomp = defined($precomp) ? "/$precomp/" : "";
- my $pmreplroot = $op->pmreplroot;
- my ($pmreplroot, $pmreplstart);
- if ($ {$pmreplroot = $op->pmreplroot} && $pmreplroot->isa("B::GV")) {
- # with C<@stash_array = split(/pat/, str);>,
- # *stash_array is stored in pmreplroot.
- $h{arg} = "($precomp => \@" . $pmreplroot->NAME . ")";
- } elsif ($ {$op->pmreplstart}) {
- undef $lastnext;
- $pmreplstart = "replstart->" . seq($op->pmreplstart);
- $h{arg} = "(" . join(" ", $precomp, $pmreplstart) . ")";
- } else {
- $h{arg} = "($precomp)";
- }
- } elsif ($h{class} eq "PVOP" and $h{name} ne "trans") {
- $h{arg} = '("' . $op->pv . '")';
- $h{svval} = '"' . $op->pv . '"';
- } elsif ($h{class} eq "COP") {
- my $label = $op->label;
- $h{coplabel} = $label;
- $label = $label ? "$label: " : "";
- my $loc = $op->file;
- $loc =~ s[.*/][];
- $loc .= ":" . $op->line;
- my($stash, $cseq) = ($op->stash->NAME, $op->cop_seq - $cop_seq_base);
- my $arybase = $op->arybase;
- $arybase = $arybase ? ' $[=' . $arybase : "";
- $h{arg} = "($label$stash $cseq $loc$arybase)";
- } elsif ($h{class} eq "LOOP") {
- $h{arg} = "(next->" . seq($op->nextop) . " last->" . seq($op->lastop)
- . " redo->" . seq($op->redoop) . ")";
- } elsif ($h{class} eq "LOGOP") {
- undef $lastnext;
- $h{arg} = "(other->" . seq($op->other) . ")";
- } elsif ($h{class} eq "SVOP") {
- my $sv = $op->sv;
- $h{svclass} = class($sv);
- $h{svaddr} = sprintf("%#x", $$sv);
- if ($h{svclass} eq "GV") {
- my $gv = $sv;
- my $stash = $gv->STASH->NAME;
- if ($stash eq "main") {
- $stash = "";
- } else {
- $stash = $stash . "::";
- }
- $h{arg} = "(*$stash" . $gv->SAFENAME . ")";
- $h{svval} = "*$stash" . $gv->SAFENAME;
- } else {
- while (class($sv) eq "RV") {
- $h{svval} .= "\\";
- $sv = $sv->RV;
- }
- if (class($sv) eq "SPECIAL") {
- $h{svval} = ["Null", "sv_undef", "sv_yes", "sv_no"]->[$$sv];
- } elsif ($sv->FLAGS & SVf_NOK) {
- $h{svval} = $sv->NV;
- } elsif ($sv->FLAGS & SVf_IOK) {
- $h{svval} = $sv->IV;
- } elsif ($sv->FLAGS & SVf_POK) {
- $h{svval} = cstring($sv->PV);
- }
- $h{arg} = "($h{svclass} $h{svval})";
- }
- }
- $h{seq} = $h{hyphseq} = seq($op);
- $h{seq} = "" if $h{seq} eq "-";
- $h{seqnum} = $op->seq;
- $h{next} = $op->next;
- $h{next} = (class($h{next}) eq "NULL") ? "(end)" : seq($h{next});
- $h{nextaddr} = sprintf("%#x", $ {$op->next});
- $h{sibaddr} = sprintf("%#x", $ {$op->sibling});
- $h{firstaddr} = sprintf("%#x", $ {$op->first}) if $op->can("first");
- $h{lastaddr} = sprintf("%#x", $ {$op->last}) if $op->can("last");
-
- $h{classsym} = $opclass{$h{class}};
- $h{flagval} = $op->flags;
- $h{flags} = op_flags($op->flags);
- $h{privval} = $op->private;
- $h{private} = private_flags($h{name}, $op->private);
- $h{addr} = sprintf("%#x", $$op);
- $h{label} = $labels{$op->seq};
- $h{typenum} = $op->type;
- $h{noise} = $linenoise[$op->type];
- return fmt_line(\%h, $format, $level);
-}
-
-sub B::OP::concise {
- my($op, $level) = @_;
- if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
- my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
- "addr" => sprintf("%#x", $$lastnext)};
- print fmt_line($h, $gotofmt, $level+1);
- }
- $lastnext = $op->next;
- print concise_op($op, $level, $format);
-}
-
-sub tree {
- my $op = shift;
- my $level = shift;
- my $style = $tree_decorations[$tree_style];
- my($space, $single, $kids, $kid, $nokid, $last, $lead, $size) = @$style;
- my $name = concise_op($op, $level, $treefmt);
- if (not $op->flags & OPf_KIDS) {
- return $name . "\n";
- }
- my @lines;
- for (my $kid = $op->first; $$kid; $kid = $kid->sibling) {
- push @lines, tree($kid, $level+1);
- }
- my $i;
- for ($i = $#lines; substr($lines[$i], 0, 1) eq " "; $i--) {
- $lines[$i] = $space . $lines[$i];
- }
- if ($i > 0) {
- $lines[$i] = $last . $lines[$i];
- while ($i-- > 1) {
- if (substr($lines[$i], 0, 1) eq " ") {
- $lines[$i] = $nokid . $lines[$i];
- } else {
- $lines[$i] = $kid . $lines[$i];
- }
- }
- $lines[$i] = $kids . $lines[$i];
- } else {
- $lines[0] = $single . $lines[0];
- }
- return("$name$lead" . shift @lines,
- map(" " x (length($name)+$size) . $_, @lines));
-}
-
-# This is a bit of a hack; the 2 and 15 were determined empirically.
-# These need to stay the last things in the module.
-$cop_seq_base = svref_2object(eval 'sub{0;}')->START->cop_seq + 2;
-$seq_base = svref_2object(eval 'sub{}')->START->seq + 15;
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Concise - Walk Perl syntax tree, printing concise info about ops
-
-=head1 SYNOPSIS
-
- perl -MO=Concise[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This compiler backend prints the internal OPs of a Perl program's syntax
-tree in one of several space-efficient text formats suitable for debugging
-the inner workings of perl or other compiler backends. It can print OPs in
-the order they appear in the OP tree, in the order they will execute, or
-in a text approximation to their tree structure, and the format of the
-information displyed is customizable. Its function is similar to that of
-perl's B<-Dx> debugging flag or the B<B::Terse> module, but it is more
-sophisticated and flexible.
-
-=head1 OPTIONS
-
-Arguments that don't start with a hyphen are taken to be the names of
-subroutines to print the OPs of; if no such functions are specified, the
-main body of the program (outside any subroutines, and not including use'd
-or require'd files) is printed.
-
-=over 4
-
-=item B<-basic>
-
-Print OPs in the order they appear in the OP tree (a preorder
-traversal, starting at the root). The indentation of each OP shows its
-level in the tree. This mode is the default, so the flag is included
-simply for completeness.
-
-=item B<-exec>
-
-Print OPs in the order they would normally execute (for the majority
-of constructs this is a postorder traversal of the tree, ending at the
-root). In most cases the OP that usually follows a given OP will
-appear directly below it; alternate paths are shown by indentation. In
-cases like loops when control jumps out of a linear path, a 'goto'
-line is generated.
-
-=item B<-tree>
-
-Print OPs in a text approximation of a tree, with the root of the tree
-at the left and 'left-to-right' order of children transformed into
-'top-to-bottom'. Because this mode grows both to the right and down,
-it isn't suitable for large programs (unless you have a very wide
-terminal).
-
-=item B<-compact>
-
-Use a tree format in which the minimum amount of space is used for the
-lines connecting nodes (one character in most cases). This squeezes out
-a few precious columns of screen real estate.
-
-=item B<-loose>
-
-Use a tree format that uses longer edges to separate OP nodes. This format
-tends to look better than the compact one, especially in ASCII, and is
-the default.
-
-=item B<-vt>
-
-Use tree connecting characters drawn from the VT100 line-drawing set.
-This looks better if your terminal supports it.
-
-=item B<-ascii>
-
-Draw the tree with standard ASCII characters like C<+> and C<|>. These don't
-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>
-
-Include the main program in the output, even if subroutines were also
-specified.
-
-=item B<-base>I<n>
-
-Print OP sequence numbers in base I<n>. If I<n> is greater than 10, the
-digit for 11 will be 'a', and so on. If I<n> is greater than 36, the digit
-for 37 will be 'A', and so on until 62. Values greater than 62 are not
-currently supported. The default is 36.
-
-=item B<-bigendian>
-
-Print sequence numbers with the most significant digit first. This is the
-usual convention for Arabic numerals, and the default.
-
-=item B<-littleendian>
-
-Print seqence numbers with the least significant digit first.
-
-=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 ouput 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>.
-
-=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 reminiscient 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
-
-=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.
-
-=over 4
-
-=item B<(x(>I<exec_text>B<;>I<basic_text>B<)x)>
-
-Generates I<exec_text> in exec mode, or I<basic_text> in basic mode.
-
-=item B<(*(>I<text>B<)*)>
-
-Generates one copy of I<text> for each indentation level.
-
-=item B<(*(>I<text1>B<;>I<text2>B<)*)>
-
-Generates one fewer copies of I<text1> than the indentation level, followed
-by one copy of I<text2> if the indentation level is more than 0.
-
-=item B<(?(>I<text1>B<#>I<var>I<Text2>B<)?)>
-
-If the value of I<var> is true (not empty or zero), generates the
-value of I<var> surrounded by I<text1> and I<Text2>, otherwise
-nothing.
-
-=item B<#>I<var>
-
-Generates the value of the variable I<var>.
-
-=item B<#>I<var>I<N>
-
-Generates the value of I<var>, left jutified to fill I<N> spaces.
-
-=item B<~>
-
-Any number of tildes and surrounding whitespace will be collapsed to
-a single space.
-
-=back
-
-The following variables are recognized:
-
-=over 4
-
-=item B<#addr>
-
-The address of the OP, in hexidecimal.
-
-=item B<#arg>
-
-The OP-specific information of the OP (such as the SV for an SVOP, the
-non-local exit pointers for a LOOP, etc.) enclosed in paretheses.
-
-=item B<#class>
-
-The B-determined class of the OP, in all caps.
-
-=item B<#classym>
-
-A single symbol abbreviating the class of the OP.
-
-=item B<#coplabel>
-
-The label of the statement or block the OP is the start of, if any.
-
-=item B<#exname>
-
-The name of the OP, or 'ex-foo' if the OP is a null that used to be a foo.
-
-=item B<#extarg>
-
-The target of the OP, or nothing for a nulled OP.
-
-=item B<#firstaddr>
-
-The address of the OP's first child, in hexidecimal.
-
-=item B<#flags>
-
-The OP's flags, abbreviated as a series of symbols.
-
-=item B<#flagval>
-
-The numeric value of the OP's flags.
-
-=item B<#hyphenseq>
-
-The sequence number of the OP, or a hyphen if it doesn't have one.
-
-=item B<#label>
-
-'NEXT', 'LAST', or 'REDO' if the OP is a target of one of those in exec
-mode, or empty otherwise.
-
-=item B<#lastaddr>
-
-The address of the OP's last child, in hexidecimal.
-
-=item B<#name>
-
-The OP's name.
-
-=item B<#NAME>
-
-The OP's name, in all caps.
-
-=item B<#next>
-
-The sequence number of the OP's next OP.
-
-=item B<#nextaddr>
-
-The address of the OP's next OP, in hexidecimal.
-
-=item B<#noise>
-
-The two-character abbreviation for the OP's name.
-
-=item B<#private>
-
-The OP's private flags, rendered with abbreviated names if possible.
-
-=item B<#privval>
-
-The numeric value of the OP's private flags.
-
-=item B<#seq>
-
-The sequence number of the OP.
-
-=item B<#seqnum>
-
-The real sequence number of the OP, as a regular number and not adjusted
-to be relative to the start of the real program. (This will generally be
-a fairly large number because all of B<B::Concise> is compiled before
-your program is).
-
-=item B<#sibaddr>
-
-The address of the OP's next youngest sibling, in hexidecimal.
-
-=item B<#svaddr>
-
-The address of the OP's SV, if it has an SV, in hexidecimal.
-
-=item B<#svclass>
-
-The class of the OP's SV, if it has one, in all caps (e.g., 'IV').
-
-=item B<#svval>
-
-The value of the OP's SV, if it has one, in a short human-readable format.
-
-=item B<#targ>
-
-The numeric value of the OP's targ.
-
-=item B<#targarg>
-
-The name of the variable the OP's targ refers to, if any, otherwise the
-letter t followed by the OP's targ in decimal.
-
-=item B<#targarglife>
-
-Same as B<#targarg>, but followed by the COP sequence numbers that delimit
-the variable's lifetime (or 'end' for a variable in an open scope) for a
-variable.
-
-=item B<#typenum>
-
-The numeric value of the OP's type, in decimal.
-
-=back
-
-=head1 ABBREVIATIONS
-
-=head2 OP flags abbreviations
-
- v OPf_WANT_VOID Want nothing (void context)
- s OPf_WANT_SCALAR Want single value (scalar context)
- l OPf_WANT_LIST Want list of any length (list context)
- K OPf_KIDS There is a firstborn child.
- P OPf_PARENS This operator was parenthesized.
- (Or block needs explicit scope entry.)
- R OPf_REF Certified reference.
- (Return container, not containee).
- M OPf_MOD Will modify (lvalue).
- S OPf_STACKED Some arg is arriving on the stack.
- * OPf_SPECIAL Do something weird for this op (see op.h)
-
-=head2 OP class abbreviations
-
- 0 OP (aka BASEOP) An OP with no children
- 1 UNOP An OP with one child
- 2 BINOP An OP with two children
- | LOGOP A control branch OP
- @ LISTOP An OP that could have lots of children
- / PMOP An OP with a regular expression
- $ SVOP An OP with an SV
- " PVOP An OP with a string
- { LOOP An OP that holds pointers for a loop
- ; COP An OP that marks the start of a statement
-
-=head1 AUTHOR
-
-Stephen McCamant, C<smcc@CSUA.Berkeley.EDU>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Debug.pm b/contrib/perl5/ext/B/B/Debug.pm
deleted file mode 100644
index 049195b..0000000
--- a/contrib/perl5/ext/B/B/Debug.pm
+++ /dev/null
@@ -1,283 +0,0 @@
-package B::Debug;
-use strict;
-use B qw(peekop class walkoptree walkoptree_exec
- main_start main_root cstring sv_undef);
-use B::Asmdata qw(@specialsv_name);
-
-my %done_gv;
-
-sub B::OP::debug {
- my ($op) = @_;
- printf <<'EOT', class($op), $$op, ${$op->next}, ${$op->sibling}, $op->ppaddr, $op->targ, $op->type, $op->seq, $op->flags, $op->private;
-%s (0x%lx)
- op_next 0x%x
- op_sibling 0x%x
- op_ppaddr %s
- op_targ %d
- op_type %d
- op_seq %d
- op_flags %d
- op_private %d
-EOT
-}
-
-sub B::UNOP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf "\top_first\t0x%x\n", ${$op->first};
-}
-
-sub B::BINOP::debug {
- my ($op) = @_;
- $op->B::UNOP::debug();
- printf "\top_last\t\t0x%x\n", ${$op->last};
-}
-
-sub B::LOOP::debug {
- my ($op) = @_;
- $op->B::BINOP::debug();
- printf <<'EOT', ${$op->redoop}, ${$op->nextop}, ${$op->lastop};
- op_redoop 0x%x
- op_nextop 0x%x
- op_lastop 0x%x
-EOT
-}
-
-sub B::LOGOP::debug {
- my ($op) = @_;
- $op->B::UNOP::debug();
- printf "\top_other\t0x%x\n", ${$op->other};
-}
-
-sub B::LISTOP::debug {
- my ($op) = @_;
- $op->B::BINOP::debug();
- printf "\top_children\t%d\n", $op->children;
-}
-
-sub B::PMOP::debug {
- my ($op) = @_;
- $op->B::LISTOP::debug();
- printf "\top_pmreplroot\t0x%x\n", ${$op->pmreplroot};
- printf "\top_pmreplstart\t0x%x\n", ${$op->pmreplstart};
- printf "\top_pmnext\t0x%x\n", ${$op->pmnext};
- printf "\top_pmregexp->precomp\t%s\n", cstring($op->precomp);
- printf "\top_pmflags\t0x%x\n", $op->pmflags;
- $op->pmreplroot->debug;
-}
-
-sub B::COP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf <<'EOT', $op->label, $op->stashpv, $op->file, $op->seq, $op->arybase, $op->line, ${$op->warnings};
- cop_label %s
- cop_stashpv %s
- cop_file %s
- cop_seq %d
- cop_arybase %d
- cop_line %d
- cop_warnings 0x%x
-EOT
-}
-
-sub B::SVOP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf "\top_sv\t\t0x%x\n", ${$op->sv};
- $op->sv->debug;
-}
-
-sub B::PVOP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf "\top_pv\t\t0x%x\n", $op->pv;
-}
-
-sub B::PADOP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf "\top_padix\t\t%ld\n", $op->padix;
-}
-
-sub B::CVOP::debug {
- my ($op) = @_;
- $op->B::OP::debug();
- printf "\top_cv\t\t0x%x\n", ${$op->cv};
-}
-
-sub B::NULL::debug {
- my ($sv) = @_;
- if ($$sv == ${sv_undef()}) {
- print "&sv_undef\n";
- } else {
- printf "NULL (0x%x)\n", $$sv;
- }
-}
-
-sub B::SV::debug {
- my ($sv) = @_;
- if (!$$sv) {
- print class($sv), " = NULL\n";
- return;
- }
- printf <<'EOT', class($sv), $$sv, $sv->REFCNT, $sv->FLAGS;
-%s (0x%x)
- REFCNT %d
- FLAGS 0x%x
-EOT
-}
-
-sub B::PV::debug {
- my ($sv) = @_;
- $sv->B::SV::debug();
- my $pv = $sv->PV();
- printf <<'EOT', cstring($pv), length($pv);
- xpv_pv %s
- xpv_cur %d
-EOT
-}
-
-sub B::IV::debug {
- my ($sv) = @_;
- $sv->B::SV::debug();
- printf "\txiv_iv\t\t%d\n", $sv->IV;
-}
-
-sub B::NV::debug {
- my ($sv) = @_;
- $sv->B::IV::debug();
- printf "\txnv_nv\t\t%s\n", $sv->NV;
-}
-
-sub B::PVIV::debug {
- my ($sv) = @_;
- $sv->B::PV::debug();
- printf "\txiv_iv\t\t%d\n", $sv->IV;
-}
-
-sub B::PVNV::debug {
- my ($sv) = @_;
- $sv->B::PVIV::debug();
- printf "\txnv_nv\t\t%s\n", $sv->NV;
-}
-
-sub B::PVLV::debug {
- my ($sv) = @_;
- $sv->B::PVNV::debug();
- printf "\txlv_targoff\t%d\n", $sv->TARGOFF;
- printf "\txlv_targlen\t%u\n", $sv->TARGLEN;
- printf "\txlv_type\t%s\n", cstring(chr($sv->TYPE));
-}
-
-sub B::BM::debug {
- my ($sv) = @_;
- $sv->B::PVNV::debug();
- printf "\txbm_useful\t%d\n", $sv->USEFUL;
- printf "\txbm_previous\t%u\n", $sv->PREVIOUS;
- printf "\txbm_rare\t%s\n", cstring(chr($sv->RARE));
-}
-
-sub B::CV::debug {
- my ($sv) = @_;
- $sv->B::PVNV::debug();
- my ($stash) = $sv->STASH;
- my ($start) = $sv->START;
- my ($root) = $sv->ROOT;
- my ($padlist) = $sv->PADLIST;
- my ($file) = $sv->FILE;
- my ($gv) = $sv->GV;
- printf <<'EOT', $$stash, $$start, $$root, $$gv, $file, $sv->DEPTH, $padlist, ${$sv->OUTSIDE};
- STASH 0x%x
- START 0x%x
- ROOT 0x%x
- GV 0x%x
- FILE %s
- DEPTH %d
- PADLIST 0x%x
- OUTSIDE 0x%x
-EOT
- $start->debug if $start;
- $root->debug if $root;
- $gv->debug if $gv;
- $padlist->debug if $padlist;
-}
-
-sub B::AV::debug {
- my ($av) = @_;
- $av->B::SV::debug;
- my(@array) = $av->ARRAY;
- print "\tARRAY\t\t(", join(", ", map("0x" . $$_, @array)), ")\n";
- printf <<'EOT', scalar(@array), $av->MAX, $av->OFF, $av->AvFLAGS;
- FILL %d
- MAX %d
- OFF %d
- AvFLAGS %d
-EOT
-}
-
-sub B::GV::debug {
- my ($gv) = @_;
- if ($done_gv{$$gv}++) {
- printf "GV %s::%s\n", $gv->STASH->NAME, $gv->SAFENAME;
- return;
- }
- my ($sv) = $gv->SV;
- my ($av) = $gv->AV;
- my ($cv) = $gv->CV;
- $gv->B::SV::debug;
- printf <<'EOT', $gv->SAFENAME, $gv->STASH->NAME, $gv->STASH, $$sv, $gv->GvREFCNT, $gv->FORM, $$av, ${$gv->HV}, ${$gv->EGV}, $$cv, $gv->CVGEN, $gv->LINE, $gv->FILE, $gv->GvFLAGS;
- NAME %s
- STASH %s (0x%x)
- SV 0x%x
- GvREFCNT %d
- FORM 0x%x
- AV 0x%x
- HV 0x%x
- EGV 0x%x
- CV 0x%x
- CVGEN %d
- LINE %d
- FILE %s
- GvFLAGS 0x%x
-EOT
- $sv->debug if $sv;
- $av->debug if $av;
- $cv->debug if $cv;
-}
-
-sub B::SPECIAL::debug {
- my $sv = shift;
- print $specialsv_name[$$sv], "\n";
-}
-
-sub compile {
- my $order = shift;
- B::clearsym();
- if ($order && $order eq "exec") {
- return sub { walkoptree_exec(main_start, "debug") }
- } else {
- return sub { walkoptree(main_root, "debug") }
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Debug - Walk Perl syntax tree, printing debug info about ops
-
-=head1 SYNOPSIS
-
- perl -MO=Debug[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-See F<ext/B/README>.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Deparse.pm b/contrib/perl5/ext/B/B/Deparse.pm
deleted file mode 100644
index ead02e1..0000000
--- a/contrib/perl5/ext/B/B/Deparse.pm
+++ /dev/null
@@ -1,3128 +0,0 @@
-# B::Deparse.pm
-# Copyright (c) 1998, 1999, 2000 Stephen McCamant. All rights reserved.
-# This module is free software; you can redistribute and/or modify
-# it under the same terms as Perl itself.
-
-# This is based on the module of the same name by Malcolm Beattie,
-# but essentially none of his code remains.
-
-package B::Deparse;
-use Carp 'cluck', 'croak';
-use B qw(class main_root main_start main_cv svref_2object opnumber
- OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
- OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL
- OPpLVAL_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
- OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY
- SVf_IOK SVf_NOK SVf_ROK SVf_POK
- CVf_METHOD CVf_LOCKED CVf_LVALUE
- PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE
- PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED);
-$VERSION = 0.60;
-use strict;
-
-# Changes between 0.50 and 0.51:
-# - fixed nulled leave with live enter in sort { }
-# - fixed reference constants (\"str")
-# - handle empty programs gracefully
-# - handle infinte loops (for (;;) {}, while (1) {})
-# - differentiate between `for my $x ...' and `my $x; for $x ...'
-# - various minor cleanups
-# - moved globals into an object
-# - added `-u', like B::C
-# - package declarations using cop_stash
-# - subs, formats and code sorted by cop_seq
-# Changes between 0.51 and 0.52:
-# - added pp_threadsv (special variables under USE_THREADS)
-# - added documentation
-# Changes between 0.52 and 0.53:
-# - many changes adding precedence contexts and associativity
-# - added `-p' and `-s' output style options
-# - various other minor fixes
-# Changes between 0.53 and 0.54:
-# - added support for new `for (1..100)' optimization,
-# thanks to Gisle Aas
-# Changes between 0.54 and 0.55:
-# - added support for new qr// construct
-# - added support for new pp_regcreset OP
-# Changes between 0.55 and 0.56:
-# - tested on base/*.t, cmd/*.t, comp/*.t, io/*.t
-# - fixed $# on non-lexicals broken in last big rewrite
-# - added temporary fix for change in opcode of OP_STRINGIFY
-# - fixed problem in 0.54's for() patch in `for (@ary)'
-# - fixed precedence in conditional of ?:
-# - tweaked list paren elimination in `my($x) = @_'
-# - made continue-block detection trickier wrt. null ops
-# - fixed various prototype problems in pp_entersub
-# - added support for sub prototypes that never get GVs
-# - added unquoting for special filehandle first arg in truncate
-# - print doubled rv2gv (a bug) as `*{*GV}' instead of illegal `**GV'
-# - added semicolons at the ends of blocks
-# - added -l `#line' declaration option -- fixes cmd/subval.t 27,28
-# Changes between 0.56 and 0.561:
-# - fixed multiply-declared my var in pp_truncate (thanks to Sarathy)
-# - used new B.pm symbolic constants (done by Nick Ing-Simmons)
-# Changes between 0.561 and 0.57:
-# - stylistic changes to symbolic constant stuff
-# - handled scope in s///e replacement code
-# - added unquote option for expanding "" into concats, etc.
-# - split method and proto parts of pp_entersub into separate functions
-# - various minor cleanups
-# Changes after 0.57:
-# - added parens in \&foo (patch by Albert Dvornik)
-# Changes between 0.57 and 0.58:
-# - fixed `0' statements that weren't being printed
-# - added methods for use from other programs
-# (based on patches from James Duncan and Hugo van der Sanden)
-# - added -si and -sT to control indenting (also based on a patch from Hugo)
-# - added -sv to print something else instead of '???'
-# - preliminary version of utf8 tr/// handling
-# Changes after 0.58:
-# - uses of $op->ppaddr changed to new $op->name (done by Sarathy)
-# - added support for Hugo's new OP_SETSTATE (like nextstate)
-# Changes between 0.58 and 0.59
-# - added support for Chip's OP_METHOD_NAMED
-# - added support for Ilya's OPpTARGET_MY optimization
-# - elided arrows before `()' subscripts when possible
-# Changes between 0.59 and 0.60
-# - support for method attribues was added
-# - some warnings fixed
-# - separate recognition of constant subs
-# - rewrote continue block handling, now recoginizing for loops
-# - added more control of expanding control structures
-
-# Todo:
-# - finish tr/// changes
-# - add option for even more parens (generalize \&foo change)
-# - {} around variables in strings ("${var}letters")
-# base/lex.t 25-27
-# comp/term.t 11
-# - left/right context
-# - recognize `use utf8', `use integer', etc
-# - treat top-level block specially for incremental output
-# - interpret high bit chars in string as utf8 \x{...} (when?)
-# - copy comments (look at real text with $^P?)
-# - avoid semis in one-statement blocks
-# - associativity of &&=, ||=, ?:
-# - ',' => '=>' (auto-unquote?)
-# - break long lines ("\r" as discretionary break?)
-# - configurable syntax highlighting: ANSI color, HTML, TeX, etc.
-# - more style options: brace style, hex vs. octal, quotes, ...
-# - print big ints as hex/octal instead of decimal (heuristic?)
-# - handle `my $x if 0'?
-# - include values of variables (e.g. set in BEGIN)
-# - coordinate with Data::Dumper (both directions? see previous)
-# - version using op_next instead of op_first/sibling?
-# - avoid string copies (pass arrays, one big join?)
-# - auto-apply `-u'?
-# - -uPackage:: descend recursively?
-# - here-docs?
-# - <DATA>?
-
-# Tests that will always fail:
-# comp/redef.t -- all (redefinition happens at compile time)
-
-# Object fields (were globals):
-#
-# avoid_local:
-# (local($a), local($b)) and local($a, $b) have the same internal
-# representation but the short form looks better. We notice we can
-# use a large-scale local when checking the list, but need to prevent
-# individual locals too. This hash holds the addresses of OPs that
-# have already had their local-ness accounted for. The same thing
-# is done with my().
-#
-# curcv:
-# CV for current sub (or main program) being deparsed
-#
-# curstash:
-# name of the current package for deparsed code
-#
-# subs_todo:
-# array of [cop_seq, GV, is_format?] for subs and formats we still
-# want to deparse
-#
-# protos_todo:
-# as above, but [name, prototype] for subs that never got a GV
-#
-# subs_done, forms_done:
-# keys are addresses of GVs for subs and formats we've already
-# deparsed (or at least put into subs_todo)
-#
-# parens: -p
-# linenums: -l
-# unquote: -q
-# cuddle: ` ' or `\n', depending on -sC
-# indent_size: -si
-# use_tabs: -sT
-# ex_const: -sv
-
-# A little explanation of how precedence contexts and associativity
-# work:
-#
-# deparse() calls each per-op subroutine with an argument $cx (short
-# for context, but not the same as the cx* in the perl core), which is
-# a number describing the op's parents in terms of precedence, whether
-# they're inside an expression or at statement level, etc. (see
-# chart below). When ops with children call deparse on them, they pass
-# along their precedence. Fractional values are used to implement
-# associativity (`($x + $y) + $z' => `$x + $y + $y') and related
-# parentheses hacks. The major disadvantage of this scheme is that
-# it doesn't know about right sides and left sides, so say if you
-# assign a listop to a variable, it can't tell it's allowed to leave
-# the parens off the listop.
-
-# Precedences:
-# 26 [TODO] inside interpolation context ("")
-# 25 left terms and list operators (leftward)
-# 24 left ->
-# 23 nonassoc ++ --
-# 22 right **
-# 21 right ! ~ \ and unary + and -
-# 20 left =~ !~
-# 19 left * / % x
-# 18 left + - .
-# 17 left << >>
-# 16 nonassoc named unary operators
-# 15 nonassoc < > <= >= lt gt le ge
-# 14 nonassoc == != <=> eq ne cmp
-# 13 left &
-# 12 left | ^
-# 11 left &&
-# 10 left ||
-# 9 nonassoc .. ...
-# 8 right ?:
-# 7 right = += -= *= etc.
-# 6 left , =>
-# 5 nonassoc list operators (rightward)
-# 4 right not
-# 3 left and
-# 2 left or xor
-# 1 statement modifiers
-# 0 statement level
-
-# Nonprinting characters with special meaning:
-# \cS - steal parens (see maybe_parens_unop)
-# \n - newline and indent
-# \t - increase indent
-# \b - decrease indent (`outdent')
-# \f - flush left (no indent)
-# \cK - kill following semicolon, if any
-
-sub null {
- my $op = shift;
- return class($op) eq "NULL";
-}
-
-sub todo {
- my $self = shift;
- my($gv, $cv, $is_form) = @_;
- my $seq;
- if (!null($cv->START) and is_state($cv->START)) {
- $seq = $cv->START->cop_seq;
- } else {
- $seq = 0;
- }
- push @{$self->{'subs_todo'}}, [$seq, $gv, $is_form];
-}
-
-sub next_todo {
- my $self = shift;
- my $ent = shift @{$self->{'subs_todo'}};
- my $name = $self->gv_name($ent->[1]);
- if ($ent->[2]) {
- return "format $name =\n"
- . $self->deparse_format($ent->[1]->FORM). "\n";
- } else {
- return "sub $name " . $self->deparse_sub($ent->[1]->CV);
- }
-}
-
-sub walk_tree {
- my($op, $sub) = @_;
- $sub->($op);
- if ($op->flags & OPf_KIDS) {
- my $kid;
- for ($kid = $op->first; not null $kid; $kid = $kid->sibling) {
- walk_tree($kid, $sub);
- }
- }
-}
-
-sub walk_sub {
- my $self = shift;
- my $cv = shift;
- my $op = $cv->ROOT;
- $op = shift if null $op;
- return if !$op or null $op;
- walk_tree($op, sub {
- my $op = shift;
- if ($op->name eq "gv") {
- my $gv = $self->gv_or_padgv($op);
- if ($op->next->name eq "entersub") {
- return if $self->{'subs_done'}{$$gv}++;
- return if class($gv->CV) eq "SPECIAL";
- $self->todo($gv, $gv->CV, 0);
- $self->walk_sub($gv->CV);
- } elsif ($op->next->name eq "enterwrite"
- or ($op->next->name eq "rv2gv"
- and $op->next->next->name eq "enterwrite")) {
- return if $self->{'forms_done'}{$$gv}++;
- return if class($gv->FORM) eq "SPECIAL";
- $self->todo($gv, $gv->FORM, 1);
- $self->walk_sub($gv->FORM);
- }
- }
- });
-}
-
-sub stash_subs {
- my $self = shift;
- my $pack = shift;
- my(%stash, @ret);
- { no strict 'refs'; %stash = svref_2object(\%{$pack . "::"})->ARRAY }
- if ($pack eq "main") {
- $pack = "";
- } else {
- $pack = $pack . "::";
- }
- my($key, $val);
- while (($key, $val) = each %stash) {
- my $class = class($val);
- if ($class eq "PV") {
- # Just a prototype
- push @{$self->{'protos_todo'}}, [$pack . $key, $val->PV];
- } elsif ($class eq "IV") {
- # Just a name
- push @{$self->{'protos_todo'}}, [$pack . $key, undef];
- } elsif ($class eq "GV") {
- if (class($val->CV) ne "SPECIAL") {
- next if $self->{'subs_done'}{$$val}++;
- $self->todo($val, $val->CV, 0);
- $self->walk_sub($val->CV);
- }
- if (class($val->FORM) ne "SPECIAL") {
- next if $self->{'forms_done'}{$$val}++;
- $self->todo($val, $val->FORM, 1);
- $self->walk_sub($val->FORM);
- }
- }
- }
-}
-
-sub print_protos {
- my $self = shift;
- my $ar;
- my @ret;
- foreach $ar (@{$self->{'protos_todo'}}) {
- my $proto = (defined $ar->[1] ? " (". $ar->[1] . ")" : "");
- push @ret, "sub " . $ar->[0] . "$proto;\n";
- }
- delete $self->{'protos_todo'};
- return @ret;
-}
-
-sub style_opts {
- my $self = shift;
- my $opts = shift;
- my $opt;
- while (length($opt = substr($opts, 0, 1))) {
- if ($opt eq "C") {
- $self->{'cuddle'} = " ";
- $opts = substr($opts, 1);
- } elsif ($opt eq "i") {
- $opts =~ s/^i(\d+)//;
- $self->{'indent_size'} = $1;
- } elsif ($opt eq "T") {
- $self->{'use_tabs'} = 1;
- $opts = substr($opts, 1);
- } elsif ($opt eq "v") {
- $opts =~ s/^v([^.]*)(.|$)//;
- $self->{'ex_const'} = $1;
- }
- }
-}
-
-sub new {
- my $class = shift;
- my $self = bless {}, $class;
- $self->{'subs_todo'} = [];
- $self->{'curstash'} = "main";
- $self->{'cuddle'} = "\n";
- $self->{'indent_size'} = 4;
- $self->{'use_tabs'} = 0;
- $self->{'expand'} = 0;
- $self->{'unquote'} = 0;
- $self->{'linenums'} = 0;
- $self->{'parens'} = 0;
- $self->{'ex_const'} = "'???'";
- while (my $arg = shift @_) {
- if (substr($arg, 0, 2) eq "-u") {
- $self->stash_subs(substr($arg, 2));
- } elsif ($arg eq "-p") {
- $self->{'parens'} = 1;
- } elsif ($arg eq "-l") {
- $self->{'linenums'} = 1;
- } elsif ($arg eq "-q") {
- $self->{'unquote'} = 1;
- } elsif (substr($arg, 0, 2) eq "-s") {
- $self->style_opts(substr $arg, 2);
- } elsif ($arg =~ /^-x(\d)$/) {
- $self->{'expand'} = $1;
- }
- }
- return $self;
-}
-
-sub compile {
- my(@args) = @_;
- return sub {
- my $self = B::Deparse->new(@args);
- $self->stash_subs("main");
- $self->{'curcv'} = main_cv;
- $self->walk_sub(main_cv, main_start);
- print $self->print_protos;
- @{$self->{'subs_todo'}} =
- sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
- print $self->indent($self->deparse(main_root, 0)), "\n"
- unless null main_root;
- my @text;
- while (scalar(@{$self->{'subs_todo'}})) {
- push @text, $self->next_todo;
- }
- print $self->indent(join("", @text)), "\n" if @text;
- }
-}
-
-sub coderef2text {
- my $self = shift;
- my $sub = shift;
- croak "Usage: ->coderef2text(CODEREF)" unless ref($sub) eq "CODE";
- return $self->indent($self->deparse_sub(svref_2object($sub)));
-}
-
-sub deparse {
- my $self = shift;
- my($op, $cx) = @_;
-# cluck if class($op) eq "NULL";
-# cluck unless $op;
-# return $self->$ {\("pp_" . $op->name)}($op, $cx);
- my $meth = "pp_" . $op->name;
- return $self->$meth($op, $cx);
-}
-
-sub indent {
- my $self = shift;
- my $txt = shift;
- my @lines = split(/\n/, $txt);
- my $leader = "";
- my $level = 0;
- my $line;
- for $line (@lines) {
- my $cmd = substr($line, 0, 1);
- if ($cmd eq "\t" or $cmd eq "\b") {
- $level += ($cmd eq "\t" ? 1 : -1) * $self->{'indent_size'};
- if ($self->{'use_tabs'}) {
- $leader = "\t" x ($level / 8) . " " x ($level % 8);
- } else {
- $leader = " " x $level;
- }
- $line = substr($line, 1);
- }
- if (substr($line, 0, 1) eq "\f") {
- $line = substr($line, 1); # no indent
- } else {
- $line = $leader . $line;
- }
- $line =~ s/\cK;?//g;
- }
- return join("\n", @lines);
-}
-
-sub deparse_sub {
- my $self = shift;
- my $cv = shift;
- my $proto = "";
- if ($cv->FLAGS & SVf_POK) {
- $proto = "(". $cv->PV . ") ";
- }
- if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) {
- $proto .= ": ";
- $proto .= "lvalue " if $cv->CvFLAGS & CVf_LVALUE;
- $proto .= "locked " if $cv->CvFLAGS & CVf_LOCKED;
- $proto .= "method " if $cv->CvFLAGS & CVf_METHOD;
- }
-
- local($self->{'curcv'}) = $cv;
- local($self->{'curstash'}) = $self->{'curstash'};
- if (not null $cv->ROOT) {
- # skip leavesub
- return $proto . "{\n\t" .
- $self->deparse($cv->ROOT->first, 0) . "\n\b}\n";
- } else { # XSUB?
- return $proto . "{}\n";
- }
-}
-
-sub deparse_format {
- my $self = shift;
- my $form = shift;
- my @text;
- local($self->{'curcv'}) = $form;
- local($self->{'curstash'}) = $self->{'curstash'};
- my $op = $form->ROOT;
- my $kid;
- $op = $op->first->first; # skip leavewrite, lineseq
- while (not null $op) {
- $op = $op->sibling; # skip nextstate
- my @exprs;
- $kid = $op->first->sibling; # skip pushmark
- push @text, $self->const_sv($kid)->PV;
- $kid = $kid->sibling;
- for (; not null $kid; $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 0);
- }
- push @text, join(", ", @exprs)."\n" if @exprs;
- $op = $op->sibling;
- }
- return join("", @text) . ".";
-}
-
-sub is_scope {
- my $op = shift;
- return $op->name eq "leave" || $op->name eq "scope"
- || $op->name eq "lineseq"
- || ($op->name eq "null" && class($op) eq "UNOP"
- && (is_scope($op->first) || $op->first->name eq "enter"));
-}
-
-sub is_state {
- my $name = $_[0]->name;
- return $name eq "nextstate" || $name eq "dbstate" || $name eq "setstate";
-}
-
-sub is_miniwhile { # check for one-line loop (`foo() while $y--')
- my $op = shift;
- return (!null($op) and null($op->sibling)
- and $op->name eq "null" and class($op) eq "UNOP"
- and (($op->first->name =~ /^(and|or)$/
- and $op->first->first->sibling->name eq "lineseq")
- or ($op->first->name eq "lineseq"
- and not null $op->first->first->sibling
- and $op->first->first->sibling->name eq "unstack")
- ));
-}
-
-sub is_scalar {
- my $op = shift;
- return ($op->name eq "rv2sv" or
- $op->name eq "padsv" or
- $op->name eq "gv" or # only in array/hash constructs
- $op->flags & OPf_KIDS && !null($op->first)
- && $op->first->name eq "gvsv");
-}
-
-sub maybe_parens {
- my $self = shift;
- my($text, $cx, $prec) = @_;
- if ($prec < $cx # unary ops nest just fine
- or $prec == $cx and $cx != 4 and $cx != 16 and $cx != 21
- or $self->{'parens'})
- {
- $text = "($text)";
- # In a unop, let parent reuse our parens; see maybe_parens_unop
- $text = "\cS" . $text if $cx == 16;
- return $text;
- } else {
- return $text;
- }
-}
-
-# same as above, but get around the `if it looks like a function' rule
-sub maybe_parens_unop {
- my $self = shift;
- my($name, $kid, $cx) = @_;
- if ($cx > 16 or $self->{'parens'}) {
- return "$name(" . $self->deparse($kid, 1) . ")";
- } else {
- $kid = $self->deparse($kid, 16);
- if (substr($kid, 0, 1) eq "\cS") {
- # use kid's parens
- return $name . substr($kid, 1);
- } elsif (substr($kid, 0, 1) eq "(") {
- # avoid looks-like-a-function trap with extra parens
- # (`+' can lead to ambiguities)
- return "$name(" . $kid . ")";
- } else {
- return "$name $kid";
- }
- }
-}
-
-sub maybe_parens_func {
- my $self = shift;
- my($func, $text, $cx, $prec) = @_;
- if ($prec <= $cx or substr($text, 0, 1) eq "(" or $self->{'parens'}) {
- return "$func($text)";
- } else {
- return "$func $text";
- }
-}
-
-sub maybe_local {
- my $self = shift;
- my($op, $cx, $text) = @_;
- if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
- if (want_scalar($op)) {
- return "local $text";
- } else {
- return $self->maybe_parens_func("local", $text, $cx, 16);
- }
- } else {
- return $text;
- }
-}
-
-sub maybe_targmy {
- my $self = shift;
- my($op, $cx, $func, @args) = @_;
- if ($op->private & OPpTARGET_MY) {
- my $var = $self->padname($op->targ);
- my $val = $func->($self, $op, 7, @args);
- return $self->maybe_parens("$var = $val", $cx, 7);
- } else {
- return $func->($self, $op, $cx, @args);
- }
-}
-
-sub padname_sv {
- my $self = shift;
- my $targ = shift;
- return (($self->{'curcv'}->PADLIST->ARRAY)[0]->ARRAY)[$targ];
-}
-
-sub maybe_my {
- my $self = shift;
- my($op, $cx, $text) = @_;
- if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
- if (want_scalar($op)) {
- return "my $text";
- } else {
- return $self->maybe_parens_func("my", $text, $cx, 16);
- }
- } else {
- return $text;
- }
-}
-
-# The following OPs don't have functions:
-
-# pp_padany -- does not exist after parsing
-# pp_rcatline -- does not exist
-
-sub pp_enter { # see also leave
- cluck "unexpected OP_ENTER";
- return "XXX";
-}
-
-sub pp_pushmark { # see also list
- cluck "unexpected OP_PUSHMARK";
- return "XXX";
-}
-
-sub pp_leavesub { # see also deparse_sub
- cluck "unexpected OP_LEAVESUB";
- return "XXX";
-}
-
-sub pp_leavewrite { # see also deparse_format
- cluck "unexpected OP_LEAVEWRITE";
- return "XXX";
-}
-
-sub pp_method { # see also entersub
- cluck "unexpected OP_METHOD";
- return "XXX";
-}
-
-sub pp_regcmaybe { # see also regcomp
- cluck "unexpected OP_REGCMAYBE";
- return "XXX";
-}
-
-sub pp_regcreset { # see also regcomp
- cluck "unexpected OP_REGCRESET";
- return "XXX";
-}
-
-sub pp_substcont { # see also subst
- cluck "unexpected OP_SUBSTCONT";
- return "XXX";
-}
-
-sub pp_grepstart { # see also grepwhile
- cluck "unexpected OP_GREPSTART";
- return "XXX";
-}
-
-sub pp_mapstart { # see also mapwhile
- cluck "unexpected OP_MAPSTART";
- return "XXX";
-}
-
-sub pp_flip { # see also flop
- cluck "unexpected OP_FLIP";
- return "XXX";
-}
-
-sub pp_iter { # see also leaveloop
- cluck "unexpected OP_ITER";
- return "XXX";
-}
-
-sub pp_enteriter { # see also leaveloop
- cluck "unexpected OP_ENTERITER";
- return "XXX";
-}
-
-sub pp_enterloop { # see also leaveloop
- cluck "unexpected OP_ENTERLOOP";
- return "XXX";
-}
-
-sub pp_leaveeval { # see also entereval
- cluck "unexpected OP_LEAVEEVAL";
- return "XXX";
-}
-
-sub pp_entertry { # see also leavetry
- cluck "unexpected OP_ENTERTRY";
- return "XXX";
-}
-
-sub lineseq {
- my $self = shift;
- my(@ops) = @_;
- my($expr, @exprs);
- for (my $i = 0; $i < @ops; $i++) {
- $expr = "";
- if (is_state $ops[$i]) {
- $expr = $self->deparse($ops[$i], 0);
- $i++;
- last if $i > $#ops;
- }
- if (!is_state $ops[$i] and $ops[$i+1] and !null($ops[$i+1]) and
- $ops[$i+1]->name eq "leaveloop" and $self->{'expand'} < 3)
- {
- push @exprs, $expr . $self->for_loop($ops[$i], 0);
- $i++;
- next;
- }
- $expr .= $self->deparse($ops[$i], 0);
- push @exprs, $expr if length $expr;
- }
- return join(";\n", @exprs);
-}
-
-sub scopeop {
- my($real_block, $self, $op, $cx) = @_;
- my $kid;
- my @kids;
- local($self->{'curstash'}) = $self->{'curstash'} if $real_block;
- if ($real_block) {
- $kid = $op->first->sibling; # skip enter
- if (is_miniwhile($kid)) {
- my $top = $kid->first;
- my $name = $top->name;
- if ($name eq "and") {
- $name = "while";
- } elsif ($name eq "or") {
- $name = "until";
- } else { # no conditional -> while 1 or until 0
- return $self->deparse($top->first, 1) . " while 1";
- }
- my $cond = $top->first;
- my $body = $cond->sibling->first; # skip lineseq
- $cond = $self->deparse($cond, 1);
- $body = $self->deparse($body, 1);
- return "$body $name $cond";
- }
- } else {
- $kid = $op->first;
- }
- for (; !null($kid); $kid = $kid->sibling) {
- push @kids, $kid;
- }
- if ($cx > 0) { # inside an expression, (a do {} while for lineseq)
- return "do { " . $self->lineseq(@kids) . " }";
- } else {
- return $self->lineseq(@kids) . ";";
- }
-}
-
-sub pp_scope { scopeop(0, @_); }
-sub pp_lineseq { scopeop(0, @_); }
-sub pp_leave { scopeop(1, @_); }
-
-# The BEGIN {} is used here because otherwise this code isn't executed
-# when you run B::Deparse on itself.
-my %globalnames;
-BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
- "ENV", "ARGV", "ARGVOUT", "_"); }
-
-sub gv_name {
- my $self = shift;
- my $gv = shift;
- my $stash = $gv->STASH->NAME;
- my $name = $gv->SAFENAME;
- if ($stash eq $self->{'curstash'} or $globalnames{$name}
- or $name =~ /^[^A-Za-z_]/)
- {
- $stash = "";
- } else {
- $stash = $stash . "::";
- }
- if ($name =~ /^\^../) {
- $name = "{$name}"; # ${^WARNING_BITS} etc
- }
- return $stash . $name;
-}
-
-# Notice how subs and formats are inserted between statements here
-sub pp_nextstate {
- my $self = shift;
- my($op, $cx) = @_;
- my @text;
- @text = $op->label . ": " if $op->label;
- my $seq = $op->cop_seq;
- while (scalar(@{$self->{'subs_todo'}})
- and $seq > $self->{'subs_todo'}[0][0]) {
- push @text, $self->next_todo;
- }
- my $stash = $op->stashpv;
- if ($stash ne $self->{'curstash'}) {
- push @text, "package $stash;\n";
- $self->{'curstash'} = $stash;
- }
- if ($self->{'linenums'}) {
- push @text, "\f#line " . $op->line .
- ' "' . $op->file, qq'"\n';
- }
- return join("", @text);
-}
-
-sub pp_dbstate { pp_nextstate(@_) }
-sub pp_setstate { pp_nextstate(@_) }
-
-sub pp_unstack { return "" } # see also leaveloop
-
-sub baseop {
- my $self = shift;
- my($op, $cx, $name) = @_;
- return $name;
-}
-
-sub pp_stub { baseop(@_, "()") }
-sub pp_wantarray { baseop(@_, "wantarray") }
-sub pp_fork { baseop(@_, "fork") }
-sub pp_wait { maybe_targmy(@_, \&baseop, "wait") }
-sub pp_getppid { maybe_targmy(@_, \&baseop, "getppid") }
-sub pp_time { maybe_targmy(@_, \&baseop, "time") }
-sub pp_tms { baseop(@_, "times") }
-sub pp_ghostent { baseop(@_, "gethostent") }
-sub pp_gnetent { baseop(@_, "getnetent") }
-sub pp_gprotoent { baseop(@_, "getprotoent") }
-sub pp_gservent { baseop(@_, "getservent") }
-sub pp_ehostent { baseop(@_, "endhostent") }
-sub pp_enetent { baseop(@_, "endnetent") }
-sub pp_eprotoent { baseop(@_, "endprotoent") }
-sub pp_eservent { baseop(@_, "endservent") }
-sub pp_gpwent { baseop(@_, "getpwent") }
-sub pp_spwent { baseop(@_, "setpwent") }
-sub pp_epwent { baseop(@_, "endpwent") }
-sub pp_ggrent { baseop(@_, "getgrent") }
-sub pp_sgrent { baseop(@_, "setgrent") }
-sub pp_egrent { baseop(@_, "endgrent") }
-sub pp_getlogin { baseop(@_, "getlogin") }
-
-sub POSTFIX () { 1 }
-
-# I couldn't think of a good short name, but this is the category of
-# symbolic unary operators with interesting precedence
-
-sub pfixop {
- my $self = shift;
- my($op, $cx, $name, $prec, $flags) = (@_, 0);
- my $kid = $op->first;
- $kid = $self->deparse($kid, $prec);
- return $self->maybe_parens(($flags & POSTFIX) ? "$kid$name" : "$name$kid",
- $cx, $prec);
-}
-
-sub pp_preinc { pfixop(@_, "++", 23) }
-sub pp_predec { pfixop(@_, "--", 23) }
-sub pp_postinc { maybe_targmy(@_, \&pfixop, "++", 23, POSTFIX) }
-sub pp_postdec { maybe_targmy(@_, \&pfixop, "--", 23, POSTFIX) }
-sub pp_i_preinc { pfixop(@_, "++", 23) }
-sub pp_i_predec { pfixop(@_, "--", 23) }
-sub pp_i_postinc { maybe_targmy(@_, \&pfixop, "++", 23, POSTFIX) }
-sub pp_i_postdec { maybe_targmy(@_, \&pfixop, "--", 23, POSTFIX) }
-sub pp_complement { maybe_targmy(@_, \&pfixop, "~", 21) }
-
-sub pp_negate { maybe_targmy(@_, \&real_negate) }
-sub real_negate {
- my $self = shift;
- my($op, $cx) = @_;
- if ($op->first->name =~ /^(i_)?negate$/) {
- # avoid --$x
- $self->pfixop($op, $cx, "-", 21.5);
- } else {
- $self->pfixop($op, $cx, "-", 21);
- }
-}
-sub pp_i_negate { pp_negate(@_) }
-
-sub pp_not {
- my $self = shift;
- my($op, $cx) = @_;
- if ($cx <= 4) {
- $self->pfixop($op, $cx, "not ", 4);
- } else {
- $self->pfixop($op, $cx, "!", 21);
- }
-}
-
-sub unop {
- my $self = shift;
- my($op, $cx, $name) = @_;
- my $kid;
- if ($op->flags & OPf_KIDS) {
- $kid = $op->first;
- return $self->maybe_parens_unop($name, $kid, $cx);
- } else {
- return $name . ($op->flags & OPf_SPECIAL ? "()" : "");
- }
-}
-
-sub pp_chop { maybe_targmy(@_, \&unop, "chop") }
-sub pp_chomp { maybe_targmy(@_, \&unop, "chomp") }
-sub pp_schop { maybe_targmy(@_, \&unop, "chop") }
-sub pp_schomp { maybe_targmy(@_, \&unop, "chomp") }
-sub pp_defined { unop(@_, "defined") }
-sub pp_undef { unop(@_, "undef") }
-sub pp_study { unop(@_, "study") }
-sub pp_ref { unop(@_, "ref") }
-sub pp_pos { maybe_local(@_, unop(@_, "pos")) }
-
-sub pp_sin { maybe_targmy(@_, \&unop, "sin") }
-sub pp_cos { maybe_targmy(@_, \&unop, "cos") }
-sub pp_rand { maybe_targmy(@_, \&unop, "rand") }
-sub pp_srand { unop(@_, "srand") }
-sub pp_exp { maybe_targmy(@_, \&unop, "exp") }
-sub pp_log { maybe_targmy(@_, \&unop, "log") }
-sub pp_sqrt { maybe_targmy(@_, \&unop, "sqrt") }
-sub pp_int { maybe_targmy(@_, \&unop, "int") }
-sub pp_hex { maybe_targmy(@_, \&unop, "hex") }
-sub pp_oct { maybe_targmy(@_, \&unop, "oct") }
-sub pp_abs { maybe_targmy(@_, \&unop, "abs") }
-
-sub pp_length { maybe_targmy(@_, \&unop, "length") }
-sub pp_ord { maybe_targmy(@_, \&unop, "ord") }
-sub pp_chr { maybe_targmy(@_, \&unop, "chr") }
-
-sub pp_each { unop(@_, "each") }
-sub pp_values { unop(@_, "values") }
-sub pp_keys { unop(@_, "keys") }
-sub pp_pop { unop(@_, "pop") }
-sub pp_shift { unop(@_, "shift") }
-
-sub pp_caller { unop(@_, "caller") }
-sub pp_reset { unop(@_, "reset") }
-sub pp_exit { unop(@_, "exit") }
-sub pp_prototype { unop(@_, "prototype") }
-
-sub pp_close { unop(@_, "close") }
-sub pp_fileno { unop(@_, "fileno") }
-sub pp_umask { unop(@_, "umask") }
-sub pp_untie { unop(@_, "untie") }
-sub pp_tied { unop(@_, "tied") }
-sub pp_dbmclose { unop(@_, "dbmclose") }
-sub pp_getc { unop(@_, "getc") }
-sub pp_eof { unop(@_, "eof") }
-sub pp_tell { unop(@_, "tell") }
-sub pp_getsockname { unop(@_, "getsockname") }
-sub pp_getpeername { unop(@_, "getpeername") }
-
-sub pp_chdir { maybe_targmy(@_, \&unop, "chdir") }
-sub pp_chroot { maybe_targmy(@_, \&unop, "chroot") }
-sub pp_readlink { unop(@_, "readlink") }
-sub pp_rmdir { maybe_targmy(@_, \&unop, "rmdir") }
-sub pp_readdir { unop(@_, "readdir") }
-sub pp_telldir { unop(@_, "telldir") }
-sub pp_rewinddir { unop(@_, "rewinddir") }
-sub pp_closedir { unop(@_, "closedir") }
-sub pp_getpgrp { maybe_targmy(@_, \&unop, "getpgrp") }
-sub pp_localtime { unop(@_, "localtime") }
-sub pp_gmtime { unop(@_, "gmtime") }
-sub pp_alarm { unop(@_, "alarm") }
-sub pp_sleep { maybe_targmy(@_, \&unop, "sleep") }
-
-sub pp_dofile { unop(@_, "do") }
-sub pp_entereval { unop(@_, "eval") }
-
-sub pp_ghbyname { unop(@_, "gethostbyname") }
-sub pp_gnbyname { unop(@_, "getnetbyname") }
-sub pp_gpbyname { unop(@_, "getprotobyname") }
-sub pp_shostent { unop(@_, "sethostent") }
-sub pp_snetent { unop(@_, "setnetent") }
-sub pp_sprotoent { unop(@_, "setprotoent") }
-sub pp_sservent { unop(@_, "setservent") }
-sub pp_gpwnam { unop(@_, "getpwnam") }
-sub pp_gpwuid { unop(@_, "getpwuid") }
-sub pp_ggrnam { unop(@_, "getgrnam") }
-sub pp_ggrgid { unop(@_, "getgrgid") }
-
-sub pp_lock { unop(@_, "lock") }
-
-sub pp_exists {
- my $self = shift;
- my($op, $cx) = @_;
- return $self->maybe_parens_func("exists", $self->pp_helem($op->first, 16),
- $cx, 16);
-}
-
-sub pp_delete {
- my $self = shift;
- my($op, $cx) = @_;
- my $arg;
- if ($op->private & OPpSLICE) {
- return $self->maybe_parens_func("delete",
- $self->pp_hslice($op->first, 16),
- $cx, 16);
- } else {
- return $self->maybe_parens_func("delete",
- $self->pp_helem($op->first, 16),
- $cx, 16);
- }
-}
-
-sub pp_require {
- my $self = shift;
- my($op, $cx) = @_;
- if (class($op) eq "UNOP" and $op->first->name eq "const"
- and $op->first->private & OPpCONST_BARE)
- {
- my $name = $self->const_sv($op->first)->PV;
- $name =~ s[/][::]g;
- $name =~ s/\.pm//g;
- return "require($name)";
- } else {
- $self->unop($op, $cx, "require");
- }
-}
-
-sub pp_scalar {
- my $self = shift;
- my($op, $cv) = @_;
- my $kid = $op->first;
- if (not null $kid->sibling) {
- # XXX Was a here-doc
- return $self->dquote($op);
- }
- $self->unop(@_, "scalar");
-}
-
-
-sub padval {
- my $self = shift;
- my $targ = shift;
- #cluck "curcv was undef" unless $self->{curcv};
- return (($self->{'curcv'}->PADLIST->ARRAY)[1]->ARRAY)[$targ];
-}
-
-sub pp_refgen {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first;
- if ($kid->name eq "null") {
- $kid = $kid->first;
- if ($kid->name eq "anonlist" || $kid->name eq "anonhash") {
- my($pre, $post) = @{{"anonlist" => ["[","]"],
- "anonhash" => ["{","}"]}->{$kid->name}};
- my($expr, @exprs);
- $kid = $kid->first->sibling; # skip pushmark
- for (; !null($kid); $kid = $kid->sibling) {
- $expr = $self->deparse($kid, 6);
- push @exprs, $expr;
- }
- return $pre . join(", ", @exprs) . $post;
- } elsif (!null($kid->sibling) and
- $kid->sibling->name eq "anoncode") {
- return "sub " .
- $self->deparse_sub($self->padval($kid->sibling->targ));
- } elsif ($kid->name eq "pushmark") {
- my $sib_name = $kid->sibling->name;
- if ($sib_name =~ /^(pad|rv2)[ah]v$/
- and not $kid->sibling->flags & OPf_REF)
- {
- # The @a in \(@a) isn't in ref context, but only when the
- # parens are there.
- return "\\(" . $self->deparse($kid->sibling, 1) . ")";
- } elsif ($sib_name eq 'entersub') {
- my $text = $self->deparse($kid->sibling, 1);
- # Always show parens for \(&func()), but only with -p otherwise
- $text = "($text)" if $self->{'parens'}
- or $kid->sibling->private & OPpENTERSUB_AMPER;
- return "\\$text";
- }
- }
- }
- $self->pfixop($op, $cx, "\\", 20);
-}
-
-sub pp_srefgen { pp_refgen(@_) }
-
-sub pp_readline {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first;
- $kid = $kid->first if $kid->name eq "rv2gv"; # <$fh>
- return "<" . $self->deparse($kid, 1) . ">";
-}
-
-# Unary operators that can occur as pseudo-listops inside double quotes
-sub dq_unop {
- my $self = shift;
- my($op, $cx, $name, $prec, $flags) = (@_, 0, 0);
- my $kid;
- if ($op->flags & OPf_KIDS) {
- $kid = $op->first;
- # If there's more than one kid, the first is an ex-pushmark.
- $kid = $kid->sibling if not null $kid->sibling;
- return $self->maybe_parens_unop($name, $kid, $cx);
- } else {
- return $name . ($op->flags & OPf_SPECIAL ? "()" : "");
- }
-}
-
-sub pp_ucfirst { dq_unop(@_, "ucfirst") }
-sub pp_lcfirst { dq_unop(@_, "lcfirst") }
-sub pp_uc { dq_unop(@_, "uc") }
-sub pp_lc { dq_unop(@_, "lc") }
-sub pp_quotemeta { maybe_targmy(@_, \&dq_unop, "quotemeta") }
-
-sub loopex {
- my $self = shift;
- my ($op, $cx, $name) = @_;
- if (class($op) eq "PVOP") {
- return "$name " . $op->pv;
- } elsif (class($op) eq "OP") {
- return $name;
- } elsif (class($op) eq "UNOP") {
- # Note -- loop exits are actually exempt from the
- # looks-like-a-func rule, but a few extra parens won't hurt
- return $self->maybe_parens_unop($name, $op->first, $cx);
- }
-}
-
-sub pp_last { loopex(@_, "last") }
-sub pp_next { loopex(@_, "next") }
-sub pp_redo { loopex(@_, "redo") }
-sub pp_goto { loopex(@_, "goto") }
-sub pp_dump { loopex(@_, "dump") }
-
-sub ftst {
- my $self = shift;
- my($op, $cx, $name) = @_;
- if (class($op) eq "UNOP") {
- # Genuine `-X' filetests are exempt from the LLAFR, but not
- # l?stat(); for the sake of clarity, give'em all parens
- return $self->maybe_parens_unop($name, $op->first, $cx);
- } elsif (class($op) eq "SVOP") {
- return $self->maybe_parens_func($name, $self->pp_gv($op, 1), $cx, 16);
- } else { # I don't think baseop filetests ever survive ck_ftst, but...
- return $name;
- }
-}
-
-sub pp_lstat { ftst(@_, "lstat") }
-sub pp_stat { ftst(@_, "stat") }
-sub pp_ftrread { ftst(@_, "-R") }
-sub pp_ftrwrite { ftst(@_, "-W") }
-sub pp_ftrexec { ftst(@_, "-X") }
-sub pp_fteread { ftst(@_, "-r") }
-sub pp_ftewrite { ftst(@_, "-r") }
-sub pp_fteexec { ftst(@_, "-r") }
-sub pp_ftis { ftst(@_, "-e") }
-sub pp_fteowned { ftst(@_, "-O") }
-sub pp_ftrowned { ftst(@_, "-o") }
-sub pp_ftzero { ftst(@_, "-z") }
-sub pp_ftsize { ftst(@_, "-s") }
-sub pp_ftmtime { ftst(@_, "-M") }
-sub pp_ftatime { ftst(@_, "-A") }
-sub pp_ftctime { ftst(@_, "-C") }
-sub pp_ftsock { ftst(@_, "-S") }
-sub pp_ftchr { ftst(@_, "-c") }
-sub pp_ftblk { ftst(@_, "-b") }
-sub pp_ftfile { ftst(@_, "-f") }
-sub pp_ftdir { ftst(@_, "-d") }
-sub pp_ftpipe { ftst(@_, "-p") }
-sub pp_ftlink { ftst(@_, "-l") }
-sub pp_ftsuid { ftst(@_, "-u") }
-sub pp_ftsgid { ftst(@_, "-g") }
-sub pp_ftsvtx { ftst(@_, "-k") }
-sub pp_fttty { ftst(@_, "-t") }
-sub pp_fttext { ftst(@_, "-T") }
-sub pp_ftbinary { ftst(@_, "-B") }
-
-sub SWAP_CHILDREN () { 1 }
-sub ASSIGN () { 2 } # has OP= variant
-
-my(%left, %right);
-
-sub assoc_class {
- my $op = shift;
- my $name = $op->name;
- if ($name eq "concat" and $op->first->name eq "concat") {
- # avoid spurious `=' -- see comment in pp_concat
- return "concat";
- }
- if ($name eq "null" and class($op) eq "UNOP"
- and $op->first->name =~ /^(and|x?or)$/
- and null $op->first->sibling)
- {
- # Like all conditional constructs, OP_ANDs and OP_ORs are topped
- # with a null that's used as the common end point of the two
- # flows of control. For precedence purposes, ignore it.
- # (COND_EXPRs have these too, but we don't bother with
- # their associativity).
- return assoc_class($op->first);
- }
- return $name . ($op->flags & OPf_STACKED ? "=" : "");
-}
-
-# Left associative operators, like `+', for which
-# $a + $b + $c is equivalent to ($a + $b) + $c
-
-BEGIN {
- %left = ('multiply' => 19, 'i_multiply' => 19,
- 'divide' => 19, 'i_divide' => 19,
- 'modulo' => 19, 'i_modulo' => 19,
- 'repeat' => 19,
- 'add' => 18, 'i_add' => 18,
- 'subtract' => 18, 'i_subtract' => 18,
- 'concat' => 18,
- 'left_shift' => 17, 'right_shift' => 17,
- 'bit_and' => 13,
- 'bit_or' => 12, 'bit_xor' => 12,
- 'and' => 3,
- 'or' => 2, 'xor' => 2,
- );
-}
-
-sub deparse_binop_left {
- my $self = shift;
- my($op, $left, $prec) = @_;
- if ($left{assoc_class($op)} && $left{assoc_class($left)}
- and $left{assoc_class($op)} == $left{assoc_class($left)})
- {
- return $self->deparse($left, $prec - .00001);
- } else {
- return $self->deparse($left, $prec);
- }
-}
-
-# Right associative operators, like `=', for which
-# $a = $b = $c is equivalent to $a = ($b = $c)
-
-BEGIN {
- %right = ('pow' => 22,
- 'sassign=' => 7, 'aassign=' => 7,
- 'multiply=' => 7, 'i_multiply=' => 7,
- 'divide=' => 7, 'i_divide=' => 7,
- 'modulo=' => 7, 'i_modulo=' => 7,
- 'repeat=' => 7,
- 'add=' => 7, 'i_add=' => 7,
- 'subtract=' => 7, 'i_subtract=' => 7,
- 'concat=' => 7,
- 'left_shift=' => 7, 'right_shift=' => 7,
- 'bit_and=' => 7,
- 'bit_or=' => 7, 'bit_xor=' => 7,
- 'andassign' => 7,
- 'orassign' => 7,
- );
-}
-
-sub deparse_binop_right {
- my $self = shift;
- my($op, $right, $prec) = @_;
- if ($right{assoc_class($op)} && $right{assoc_class($right)}
- and $right{assoc_class($op)} == $right{assoc_class($right)})
- {
- return $self->deparse($right, $prec - .00001);
- } else {
- return $self->deparse($right, $prec);
- }
-}
-
-sub binop {
- my $self = shift;
- my ($op, $cx, $opname, $prec, $flags) = (@_, 0);
- my $left = $op->first;
- my $right = $op->last;
- my $eq = "";
- if ($op->flags & OPf_STACKED && $flags & ASSIGN) {
- $eq = "=";
- $prec = 7;
- }
- if ($flags & SWAP_CHILDREN) {
- ($left, $right) = ($right, $left);
- }
- $left = $self->deparse_binop_left($op, $left, $prec);
- $right = $self->deparse_binop_right($op, $right, $prec);
- return $self->maybe_parens("$left $opname$eq $right", $cx, $prec);
-}
-
-sub pp_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) }
-sub pp_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) }
-sub pp_subtract { maybe_targmy(@_, \&binop, "-",18, ASSIGN) }
-sub pp_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) }
-sub pp_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) }
-sub pp_i_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) }
-sub pp_i_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) }
-sub pp_i_subtract { maybe_targmy(@_, \&binop, "-", 18, ASSIGN) }
-sub pp_i_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) }
-sub pp_i_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) }
-sub pp_pow { maybe_targmy(@_, \&binop, "**", 22, ASSIGN) }
-
-sub pp_left_shift { maybe_targmy(@_, \&binop, "<<", 17, ASSIGN) }
-sub pp_right_shift { maybe_targmy(@_, \&binop, ">>", 17, ASSIGN) }
-sub pp_bit_and { maybe_targmy(@_, \&binop, "&", 13, ASSIGN) }
-sub pp_bit_or { maybe_targmy(@_, \&binop, "|", 12, ASSIGN) }
-sub pp_bit_xor { maybe_targmy(@_, \&binop, "^", 12, ASSIGN) }
-
-sub pp_eq { binop(@_, "==", 14) }
-sub pp_ne { binop(@_, "!=", 14) }
-sub pp_lt { binop(@_, "<", 15) }
-sub pp_gt { binop(@_, ">", 15) }
-sub pp_ge { binop(@_, ">=", 15) }
-sub pp_le { binop(@_, "<=", 15) }
-sub pp_ncmp { binop(@_, "<=>", 14) }
-sub pp_i_eq { binop(@_, "==", 14) }
-sub pp_i_ne { binop(@_, "!=", 14) }
-sub pp_i_lt { binop(@_, "<", 15) }
-sub pp_i_gt { binop(@_, ">", 15) }
-sub pp_i_ge { binop(@_, ">=", 15) }
-sub pp_i_le { binop(@_, "<=", 15) }
-sub pp_i_ncmp { binop(@_, "<=>", 14) }
-
-sub pp_seq { binop(@_, "eq", 14) }
-sub pp_sne { binop(@_, "ne", 14) }
-sub pp_slt { binop(@_, "lt", 15) }
-sub pp_sgt { binop(@_, "gt", 15) }
-sub pp_sge { binop(@_, "ge", 15) }
-sub pp_sle { binop(@_, "le", 15) }
-sub pp_scmp { binop(@_, "cmp", 14) }
-
-sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }
-sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN) }
-
-# `.' is special because concats-of-concats are optimized to save copying
-# by making all but the first concat stacked. The effect is as if the
-# programmer had written `($a . $b) .= $c', except legal.
-sub pp_concat { maybe_targmy(@_, \&real_concat) }
-sub real_concat {
- my $self = shift;
- my($op, $cx) = @_;
- my $left = $op->first;
- my $right = $op->last;
- my $eq = "";
- my $prec = 18;
- if ($op->flags & OPf_STACKED and $op->first->name ne "concat") {
- $eq = "=";
- $prec = 7;
- }
- $left = $self->deparse_binop_left($op, $left, $prec);
- $right = $self->deparse_binop_right($op, $right, $prec);
- return $self->maybe_parens("$left .$eq $right", $cx, $prec);
-}
-
-# `x' is weird when the left arg is a list
-sub pp_repeat {
- my $self = shift;
- my($op, $cx) = @_;
- my $left = $op->first;
- my $right = $op->last;
- my $eq = "";
- my $prec = 19;
- if ($op->flags & OPf_STACKED) {
- $eq = "=";
- $prec = 7;
- }
- if (null($right)) { # list repeat; count is inside left-side ex-list
- my $kid = $left->first->sibling; # skip pushmark
- my @exprs;
- for (; !null($kid->sibling); $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 6);
- }
- $right = $kid;
- $left = "(" . join(", ", @exprs). ")";
- } else {
- $left = $self->deparse_binop_left($op, $left, $prec);
- }
- $right = $self->deparse_binop_right($op, $right, $prec);
- return $self->maybe_parens("$left x$eq $right", $cx, $prec);
-}
-
-sub range {
- my $self = shift;
- my ($op, $cx, $type) = @_;
- my $left = $op->first;
- my $right = $left->sibling;
- $left = $self->deparse($left, 9);
- $right = $self->deparse($right, 9);
- return $self->maybe_parens("$left $type $right", $cx, 9);
-}
-
-sub pp_flop {
- my $self = shift;
- my($op, $cx) = @_;
- my $flip = $op->first;
- my $type = ($flip->flags & OPf_SPECIAL) ? "..." : "..";
- return $self->range($flip->first, $cx, $type);
-}
-
-# one-line while/until is handled in pp_leave
-
-sub logop {
- my $self = shift;
- my ($op, $cx, $lowop, $lowprec, $highop, $highprec, $blockname) = @_;
- my $left = $op->first;
- my $right = $op->first->sibling;
- if ($cx == 0 and is_scope($right) and $blockname
- and $self->{'expand'} < 7)
- { # if ($a) {$b}
- $left = $self->deparse($left, 1);
- $right = $self->deparse($right, 0);
- return "$blockname ($left) {\n\t$right\n\b}\cK";
- } elsif ($cx == 0 and $blockname and not $self->{'parens'}
- and $self->{'expand'} < 7) { # $b if $a
- $right = $self->deparse($right, 1);
- $left = $self->deparse($left, 1);
- return "$right $blockname $left";
- } elsif ($cx > $lowprec and $highop) { # $a && $b
- $left = $self->deparse_binop_left($op, $left, $highprec);
- $right = $self->deparse_binop_right($op, $right, $highprec);
- return $self->maybe_parens("$left $highop $right", $cx, $highprec);
- } else { # $a and $b
- $left = $self->deparse_binop_left($op, $left, $lowprec);
- $right = $self->deparse_binop_right($op, $right, $lowprec);
- return $self->maybe_parens("$left $lowop $right", $cx, $lowprec);
- }
-}
-
-sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }
-sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
-
-# xor is syntactically a logop, but it's really a binop (contrary to
-# old versions of opcode.pl). Syntax is what matters here.
-sub pp_xor { logop(@_, "xor", 2, "", 0, "") }
-
-sub logassignop {
- my $self = shift;
- my ($op, $cx, $opname) = @_;
- my $left = $op->first;
- my $right = $op->first->sibling->first; # skip sassign
- $left = $self->deparse($left, 7);
- $right = $self->deparse($right, 7);
- return $self->maybe_parens("$left $opname $right", $cx, 7);
-}
-
-sub pp_andassign { logassignop(@_, "&&=") }
-sub pp_orassign { logassignop(@_, "||=") }
-
-sub listop {
- my $self = shift;
- my($op, $cx, $name) = @_;
- my(@exprs);
- my $parens = ($cx >= 5) || $self->{'parens'};
- my $kid = $op->first->sibling;
- return $name if null $kid;
- my $first = $self->deparse($kid, 6);
- $first = "+$first" if not $parens and substr($first, 0, 1) eq "(";
- push @exprs, $first;
- $kid = $kid->sibling;
- for (; !null($kid); $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 6);
- }
- if ($parens) {
- return "$name(" . join(", ", @exprs) . ")";
- } else {
- return "$name " . join(", ", @exprs);
- }
-}
-
-sub pp_bless { listop(@_, "bless") }
-sub pp_atan2 { maybe_targmy(@_, \&listop, "atan2") }
-sub pp_substr { maybe_local(@_, listop(@_, "substr")) }
-sub pp_vec { maybe_local(@_, listop(@_, "vec")) }
-sub pp_index { maybe_targmy(@_, \&listop, "index") }
-sub pp_rindex { maybe_targmy(@_, \&listop, "rindex") }
-sub pp_sprintf { maybe_targmy(@_, \&listop, "sprintf") }
-sub pp_formline { listop(@_, "formline") } # see also deparse_format
-sub pp_crypt { maybe_targmy(@_, \&listop, "crypt") }
-sub pp_unpack { listop(@_, "unpack") }
-sub pp_pack { listop(@_, "pack") }
-sub pp_join { maybe_targmy(@_, \&listop, "join") }
-sub pp_splice { listop(@_, "splice") }
-sub pp_push { maybe_targmy(@_, \&listop, "push") }
-sub pp_unshift { maybe_targmy(@_, \&listop, "unshift") }
-sub pp_reverse { listop(@_, "reverse") }
-sub pp_warn { listop(@_, "warn") }
-sub pp_die { listop(@_, "die") }
-# Actually, return is exempt from the LLAFR (see examples in this very
-# module!), but for consistency's sake, ignore that fact
-sub pp_return { listop(@_, "return") }
-sub pp_open { listop(@_, "open") }
-sub pp_pipe_op { listop(@_, "pipe") }
-sub pp_tie { listop(@_, "tie") }
-sub pp_binmode { listop(@_, "binmode") }
-sub pp_dbmopen { listop(@_, "dbmopen") }
-sub pp_sselect { listop(@_, "select") }
-sub pp_select { listop(@_, "select") }
-sub pp_read { listop(@_, "read") }
-sub pp_sysopen { listop(@_, "sysopen") }
-sub pp_sysseek { listop(@_, "sysseek") }
-sub pp_sysread { listop(@_, "sysread") }
-sub pp_syswrite { listop(@_, "syswrite") }
-sub pp_send { listop(@_, "send") }
-sub pp_recv { listop(@_, "recv") }
-sub pp_seek { listop(@_, "seek") }
-sub pp_fcntl { listop(@_, "fcntl") }
-sub pp_ioctl { listop(@_, "ioctl") }
-sub pp_flock { maybe_targmy(@_, \&listop, "flock") }
-sub pp_socket { listop(@_, "socket") }
-sub pp_sockpair { listop(@_, "sockpair") }
-sub pp_bind { listop(@_, "bind") }
-sub pp_connect { listop(@_, "connect") }
-sub pp_listen { listop(@_, "listen") }
-sub pp_accept { listop(@_, "accept") }
-sub pp_shutdown { listop(@_, "shutdown") }
-sub pp_gsockopt { listop(@_, "getsockopt") }
-sub pp_ssockopt { listop(@_, "setsockopt") }
-sub pp_chown { maybe_targmy(@_, \&listop, "chown") }
-sub pp_unlink { maybe_targmy(@_, \&listop, "unlink") }
-sub pp_chmod { maybe_targmy(@_, \&listop, "chmod") }
-sub pp_utime { maybe_targmy(@_, \&listop, "utime") }
-sub pp_rename { maybe_targmy(@_, \&listop, "rename") }
-sub pp_link { maybe_targmy(@_, \&listop, "link") }
-sub pp_symlink { maybe_targmy(@_, \&listop, "symlink") }
-sub pp_mkdir { maybe_targmy(@_, \&listop, "mkdir") }
-sub pp_open_dir { listop(@_, "opendir") }
-sub pp_seekdir { listop(@_, "seekdir") }
-sub pp_waitpid { maybe_targmy(@_, \&listop, "waitpid") }
-sub pp_system { maybe_targmy(@_, \&listop, "system") }
-sub pp_exec { maybe_targmy(@_, \&listop, "exec") }
-sub pp_kill { maybe_targmy(@_, \&listop, "kill") }
-sub pp_setpgrp { maybe_targmy(@_, \&listop, "setpgrp") }
-sub pp_getpriority { maybe_targmy(@_, \&listop, "getpriority") }
-sub pp_setpriority { maybe_targmy(@_, \&listop, "setpriority") }
-sub pp_shmget { listop(@_, "shmget") }
-sub pp_shmctl { listop(@_, "shmctl") }
-sub pp_shmread { listop(@_, "shmread") }
-sub pp_shmwrite { listop(@_, "shmwrite") }
-sub pp_msgget { listop(@_, "msgget") }
-sub pp_msgctl { listop(@_, "msgctl") }
-sub pp_msgsnd { listop(@_, "msgsnd") }
-sub pp_msgrcv { listop(@_, "msgrcv") }
-sub pp_semget { listop(@_, "semget") }
-sub pp_semctl { listop(@_, "semctl") }
-sub pp_semop { listop(@_, "semop") }
-sub pp_ghbyaddr { listop(@_, "gethostbyaddr") }
-sub pp_gnbyaddr { listop(@_, "getnetbyaddr") }
-sub pp_gpbynumber { listop(@_, "getprotobynumber") }
-sub pp_gsbyname { listop(@_, "getservbyname") }
-sub pp_gsbyport { listop(@_, "getservbyport") }
-sub pp_syscall { listop(@_, "syscall") }
-
-sub pp_glob {
- my $self = shift;
- my($op, $cx) = @_;
- my $text = $self->dq($op->first->sibling); # skip pushmark
- if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline
- or $text =~ /[<>]/) {
- return 'glob(' . single_delim('qq', '"', $text) . ')';
- } else {
- return '<' . $text . '>';
- }
-}
-
-# Truncate is special because OPf_SPECIAL makes a bareword first arg
-# be a filehandle. This could probably be better fixed in the core
-# by moving the GV lookup into ck_truc.
-
-sub pp_truncate {
- my $self = shift;
- my($op, $cx) = @_;
- my(@exprs);
- my $parens = ($cx >= 5) || $self->{'parens'};
- my $kid = $op->first->sibling;
- my $fh;
- if ($op->flags & OPf_SPECIAL) {
- # $kid is an OP_CONST
- $fh = $self->const_sv($kid)->PV;
- } else {
- $fh = $self->deparse($kid, 6);
- $fh = "+$fh" if not $parens and substr($fh, 0, 1) eq "(";
- }
- my $len = $self->deparse($kid->sibling, 6);
- if ($parens) {
- return "truncate($fh, $len)";
- } else {
- return "truncate $fh, $len";
- }
-}
-
-sub indirop {
- my $self = shift;
- my($op, $cx, $name) = @_;
- my($expr, @exprs);
- my $kid = $op->first->sibling;
- my $indir = "";
- if ($op->flags & OPf_STACKED) {
- $indir = $kid;
- $indir = $indir->first; # skip rv2gv
- if (is_scope($indir)) {
- $indir = "{" . $self->deparse($indir, 0) . "}";
- } else {
- $indir = $self->deparse($indir, 24);
- }
- $indir = $indir . " ";
- $kid = $kid->sibling;
- }
- for (; !null($kid); $kid = $kid->sibling) {
- $expr = $self->deparse($kid, 6);
- push @exprs, $expr;
- }
- return $self->maybe_parens_func($name, $indir . join(", ", @exprs),
- $cx, 5);
-}
-
-sub pp_prtf { indirop(@_, "printf") }
-sub pp_print { indirop(@_, "print") }
-sub pp_sort { indirop(@_, "sort") }
-
-sub mapop {
- my $self = shift;
- my($op, $cx, $name) = @_;
- my($expr, @exprs);
- my $kid = $op->first; # this is the (map|grep)start
- $kid = $kid->first->sibling; # skip a pushmark
- my $code = $kid->first; # skip a null
- if (is_scope $code) {
- $code = "{" . $self->deparse($code, 0) . "} ";
- } else {
- $code = $self->deparse($code, 24) . ", ";
- }
- $kid = $kid->sibling;
- for (; !null($kid); $kid = $kid->sibling) {
- $expr = $self->deparse($kid, 6);
- push @exprs, $expr if $expr;
- }
- return $self->maybe_parens_func($name, $code . join(", ", @exprs), $cx, 5);
-}
-
-sub pp_mapwhile { mapop(@_, "map") }
-sub pp_grepwhile { mapop(@_, "grep") }
-
-sub pp_list {
- my $self = shift;
- my($op, $cx) = @_;
- my($expr, @exprs);
- my $kid = $op->first->sibling; # skip pushmark
- my $lop;
- my $local = "either"; # could be local(...) or my(...)
- for ($lop = $kid; !null($lop); $lop = $lop->sibling) {
- # This assumes that no other private flags equal 128, and that
- # OPs that store things other than flags in their op_private,
- # like OP_AELEMFAST, won't be immediate children of a list.
- unless ($lop->private & OPpLVAL_INTRO or $lop->name eq "undef")
- {
- $local = ""; # or not
- last;
- }
- if ($lop->name =~ /^pad[ash]v$/) { # my()
- ($local = "", last) if $local eq "local";
- $local = "my";
- } elsif ($lop->name ne "undef") { # local()
- ($local = "", last) if $local eq "my";
- $local = "local";
- }
- }
- $local = "" if $local eq "either"; # no point if it's all undefs
- return $self->deparse($kid, $cx) if null $kid->sibling and not $local;
- for (; !null($kid); $kid = $kid->sibling) {
- if ($local) {
- if (class($kid) eq "UNOP" and $kid->first->name eq "gvsv") {
- $lop = $kid->first;
- } else {
- $lop = $kid;
- }
- $self->{'avoid_local'}{$$lop}++;
- $expr = $self->deparse($kid, 6);
- delete $self->{'avoid_local'}{$$lop};
- } else {
- $expr = $self->deparse($kid, 6);
- }
- push @exprs, $expr;
- }
- if ($local) {
- return "$local(" . join(", ", @exprs) . ")";
- } else {
- return $self->maybe_parens( join(", ", @exprs), $cx, 6);
- }
-}
-
-sub is_ifelse_cont {
- my $op = shift;
- return ($op->name eq "null" and class($op) eq "UNOP"
- and $op->first->name =~ /^(and|cond_expr)$/
- and is_scope($op->first->first->sibling));
-}
-
-sub pp_cond_expr {
- my $self = shift;
- my($op, $cx) = @_;
- my $cond = $op->first;
- my $true = $cond->sibling;
- my $false = $true->sibling;
- my $cuddle = $self->{'cuddle'};
- unless ($cx == 0 and (is_scope($true) and $true->name ne "null") and
- (is_scope($false) || is_ifelse_cont($false))
- and $self->{'expand'} < 7) {
- $cond = $self->deparse($cond, 8);
- $true = $self->deparse($true, 8);
- $false = $self->deparse($false, 8);
- return $self->maybe_parens("$cond ? $true : $false", $cx, 8);
- }
-
- $cond = $self->deparse($cond, 1);
- $true = $self->deparse($true, 0);
- my $head = "if ($cond) {\n\t$true\n\b}";
- my @elsifs;
- while (!null($false) and is_ifelse_cont($false)) {
- my $newop = $false->first;
- my $newcond = $newop->first;
- my $newtrue = $newcond->sibling;
- $false = $newtrue->sibling; # last in chain is OP_AND => no else
- $newcond = $self->deparse($newcond, 1);
- $newtrue = $self->deparse($newtrue, 0);
- push @elsifs, "elsif ($newcond) {\n\t$newtrue\n\b}";
- }
- if (!null($false)) {
- $false = $cuddle . "else {\n\t" .
- $self->deparse($false, 0) . "\n\b}\cK";
- } else {
- $false = "\cK";
- }
- return $head . join($cuddle, "", @elsifs) . $false;
-}
-
-sub loop_common {
- my $self = shift;
- my($op, $cx, $init) = @_;
- my $enter = $op->first;
- my $kid = $enter->sibling;
- local($self->{'curstash'}) = $self->{'curstash'};
- my $head = "";
- my $bare = 0;
- my $body;
- my $cond = undef;
- if ($kid->name eq "lineseq") { # bare or infinite loop
- if (is_state $kid->last) { # infinite
- $head = "for (;;) "; # shorter than while (1)
- $cond = "";
- } else {
- $bare = 1;
- }
- $body = $kid;
- } elsif ($enter->name eq "enteriter") { # foreach
- my $ary = $enter->first->sibling; # first was pushmark
- my $var = $ary->sibling;
- if ($enter->flags & OPf_STACKED
- and not null $ary->first->sibling->sibling)
- {
- $ary = $self->deparse($ary->first->sibling, 9) . " .. " .
- $self->deparse($ary->first->sibling->sibling, 9);
- } else {
- $ary = $self->deparse($ary, 1);
- }
- if (null $var) {
- if ($enter->flags & OPf_SPECIAL) { # thread special var
- $var = $self->pp_threadsv($enter, 1);
- } else { # regular my() variable
- $var = $self->pp_padsv($enter, 1);
- if ($self->padname_sv($enter->targ)->IVX ==
- $kid->first->first->sibling->last->cop_seq)
- {
- # If the scope of this variable closes at the last
- # statement of the loop, it must have been
- # declared here.
- $var = "my " . $var;
- }
- }
- } elsif ($var->name eq "rv2gv") {
- $var = $self->pp_rv2sv($var, 1);
- } elsif ($var->name eq "gv") {
- $var = "\$" . $self->deparse($var, 1);
- }
- $head = "foreach $var ($ary) ";
- $body = $kid->first->first->sibling; # skip OP_AND and OP_ITER
- } elsif ($kid->name eq "null") { # while/until
- $kid = $kid->first;
- my $name = {"and" => "while", "or" => "until"}->{$kid->name};
- $cond = $self->deparse($kid->first, 1);
- $head = "$name ($cond) ";
- $body = $kid->first->sibling;
- } elsif ($kid->name eq "stub") { # bare and empty
- return "{;}"; # {} could be a hashref
- }
- # If there isn't a continue block, then the next pointer for the loop
- # will point to the unstack, which is kid's penultimate child, except
- # in a bare loop, when it will point to the leaveloop. When neither of
- # these conditions hold, then the third-to-last child in the continue
- # block (or the last in a bare loop).
- my $cont_start = $enter->nextop;
- my $cont;
- if ($$cont_start != $$op and $ {$cont_start->sibling} != $ {$body->last}) {
- if ($bare) {
- $cont = $body->last;
- } else {
- $cont = $body->first;
- while (!null($cont->sibling->sibling->sibling)) {
- $cont = $cont->sibling;
- }
- }
- my $state = $body->first;
- my $cuddle = $self->{'cuddle'};
- my @states;
- for (; $$state != $$cont; $state = $state->sibling) {
- push @states, $state;
- }
- $body = $self->lineseq(@states);
- if (defined $cond and not is_scope $cont and $self->{'expand'} < 3) {
- $head = "for ($init; $cond; " . $self->deparse($cont, 1) .") ";
- $cont = "\cK";
- } else {
- $cont = $cuddle . "continue {\n\t" .
- $self->deparse($cont, 0) . "\n\b}\cK";
- }
- } else {
- $cont = "\cK";
- $body = $self->deparse($body, 0);
- }
- return $head . "{\n\t" . $body . "\n\b}" . $cont;
-}
-
-sub pp_leaveloop { loop_common(@_, "") }
-
-sub for_loop {
- my $self = shift;
- my($op, $cx) = @_;
- my $init = $self->deparse($op, 1);
- return $self->loop_common($op->sibling, $cx, $init);
-}
-
-sub pp_leavetry {
- my $self = shift;
- return "eval {\n\t" . $self->pp_leave(@_) . "\n\b}";
-}
-
-BEGIN { eval "sub OP_CONST () {" . opnumber("const") . "}" }
-BEGIN { eval "sub OP_STRINGIFY () {" . opnumber("stringify") . "}" }
-
-sub pp_null {
- my $self = shift;
- my($op, $cx) = @_;
- if (class($op) eq "OP") {
- # old value is lost
- return $self->{'ex_const'} if $op->targ == OP_CONST;
- } elsif ($op->first->name eq "pushmark") {
- return $self->pp_list($op, $cx);
- } elsif ($op->first->name eq "enter") {
- return $self->pp_leave($op, $cx);
- } elsif ($op->targ == OP_STRINGIFY) {
- return $self->dquote($op, $cx);
- } elsif (!null($op->first->sibling) and
- $op->first->sibling->name eq "readline" and
- $op->first->sibling->flags & OPf_STACKED) {
- return $self->maybe_parens($self->deparse($op->first, 7) . " = "
- . $self->deparse($op->first->sibling, 7),
- $cx, 7);
- } elsif (!null($op->first->sibling) and
- $op->first->sibling->name eq "trans" and
- $op->first->sibling->flags & OPf_STACKED) {
- return $self->maybe_parens($self->deparse($op->first, 20) . " =~ "
- . $self->deparse($op->first->sibling, 20),
- $cx, 20);
- } else {
- return $self->deparse($op->first, $cx);
- }
-}
-
-sub padname {
- my $self = shift;
- my $targ = shift;
- return $self->padname_sv($targ)->PVX;
-}
-
-sub padany {
- my $self = shift;
- my $op = shift;
- return substr($self->padname($op->targ), 1); # skip $/@/%
-}
-
-sub pp_padsv {
- my $self = shift;
- my($op, $cx) = @_;
- return $self->maybe_my($op, $cx, $self->padname($op->targ));
-}
-
-sub pp_padav { pp_padsv(@_) }
-sub pp_padhv { pp_padsv(@_) }
-
-my @threadsv_names;
-
-BEGIN {
- @threadsv_names = ("_", "1", "2", "3", "4", "5", "6", "7", "8", "9",
- "&", "`", "'", "+", "/", ".", ",", "\\", '"', ";",
- "^", "-", "%", "=", "|", "~", ":", "^A", "^E",
- "!", "@");
-}
-
-sub pp_threadsv {
- my $self = shift;
- my($op, $cx) = @_;
- return $self->maybe_local($op, $cx, "\$" . $threadsv_names[$op->targ]);
-}
-
-sub gv_or_padgv {
- my $self = shift;
- my $op = shift;
- if (class($op) eq "PADOP") {
- return $self->padval($op->padix);
- } else { # class($op) eq "SVOP"
- return $op->gv;
- }
-}
-
-sub pp_gvsv {
- my $self = shift;
- my($op, $cx) = @_;
- my $gv = $self->gv_or_padgv($op);
- return $self->maybe_local($op, $cx, "\$" . $self->gv_name($gv));
-}
-
-sub pp_gv {
- my $self = shift;
- my($op, $cx) = @_;
- my $gv = $self->gv_or_padgv($op);
- return $self->gv_name($gv);
-}
-
-sub pp_aelemfast {
- my $self = shift;
- my($op, $cx) = @_;
- my $gv = $self->gv_or_padgv($op);
- return "\$" . $self->gv_name($gv) . "[" . $op->private . "]";
-}
-
-sub rv2x {
- my $self = shift;
- my($op, $cx, $type) = @_;
- my $kid = $op->first;
- my $str = $self->deparse($kid, 0);
- return $type . (is_scalar($kid) ? $str : "{$str}");
-}
-
-sub pp_rv2sv { maybe_local(@_, rv2x(@_, "\$")) }
-sub pp_rv2hv { maybe_local(@_, rv2x(@_, "%")) }
-sub pp_rv2gv { maybe_local(@_, rv2x(@_, "*")) }
-
-# skip rv2av
-sub pp_av2arylen {
- my $self = shift;
- my($op, $cx) = @_;
- if ($op->first->name eq "padav") {
- return $self->maybe_local($op, $cx, '$#' . $self->padany($op->first));
- } else {
- return $self->maybe_local($op, $cx,
- $self->rv2x($op->first, $cx, '$#'));
- }
-}
-
-# skip down to the old, ex-rv2cv
-sub pp_rv2cv { $_[0]->rv2x($_[1]->first->first->sibling, $_[2], "&") }
-
-sub pp_rv2av {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first;
- if ($kid->name eq "const") { # constant list
- my $av = $self->const_sv($kid);
- return "(" . join(", ", map(const($_), $av->ARRAY)) . ")";
- } else {
- return $self->maybe_local($op, $cx, $self->rv2x($op, $cx, "\@"));
- }
- }
-
-sub is_subscriptable {
- my $op = shift;
- if ($op->name =~ /^[ahg]elem/) {
- return 1;
- } elsif ($op->name eq "entersub") {
- my $kid = $op->first;
- return 0 unless null $kid->sibling;
- $kid = $kid->first;
- $kid = $kid->sibling until null $kid->sibling;
- return 0 if is_scope($kid);
- $kid = $kid->first;
- return 0 if $kid->name eq "gv";
- return 0 if is_scalar($kid);
- return is_subscriptable($kid);
- } else {
- return 0;
- }
-}
-
-sub elem {
- my $self = shift;
- my ($op, $cx, $left, $right, $padname) = @_;
- my($array, $idx) = ($op->first, $op->first->sibling);
- unless ($array->name eq $padname) { # Maybe this has been fixed
- $array = $array->first; # skip rv2av (or ex-rv2av in _53+)
- }
- if ($array->name eq $padname) {
- $array = $self->padany($array);
- } elsif (is_scope($array)) { # ${expr}[0]
- $array = "{" . $self->deparse($array, 0) . "}";
- } elsif (is_scalar $array) { # $x[0], $$x[0], ...
- $array = $self->deparse($array, 24);
- } else {
- # $x[20][3]{hi} or expr->[20]
- my $arrow = is_subscriptable($array) ? "" : "->";
- return $self->deparse($array, 24) . $arrow .
- $left . $self->deparse($idx, 1) . $right;
- }
- $idx = $self->deparse($idx, 1);
- return "\$" . $array . $left . $idx . $right;
-}
-
-sub pp_aelem { maybe_local(@_, elem(@_, "[", "]", "padav")) }
-sub pp_helem { maybe_local(@_, elem(@_, "{", "}", "padhv")) }
-
-sub pp_gelem {
- my $self = shift;
- my($op, $cx) = @_;
- my($glob, $part) = ($op->first, $op->last);
- $glob = $glob->first; # skip rv2gv
- $glob = $glob->first if $glob->name eq "rv2gv"; # this one's a bug
- my $scope = is_scope($glob);
- $glob = $self->deparse($glob, 0);
- $part = $self->deparse($part, 1);
- return "*" . ($scope ? "{$glob}" : $glob) . "{$part}";
-}
-
-sub slice {
- my $self = shift;
- my ($op, $cx, $left, $right, $regname, $padname) = @_;
- my $last;
- my(@elems, $kid, $array, $list);
- if (class($op) eq "LISTOP") {
- $last = $op->last;
- } else { # ex-hslice inside delete()
- for ($kid = $op->first; !null $kid->sibling; $kid = $kid->sibling) {}
- $last = $kid;
- }
- $array = $last;
- $array = $array->first
- if $array->name eq $regname or $array->name eq "null";
- if (is_scope($array)) {
- $array = "{" . $self->deparse($array, 0) . "}";
- } elsif ($array->name eq $padname) {
- $array = $self->padany($array);
- } else {
- $array = $self->deparse($array, 24);
- }
- $kid = $op->first->sibling; # skip pushmark
- if ($kid->name eq "list") {
- $kid = $kid->first->sibling; # skip list, pushmark
- for (; !null $kid; $kid = $kid->sibling) {
- push @elems, $self->deparse($kid, 6);
- }
- $list = join(", ", @elems);
- } else {
- $list = $self->deparse($kid, 1);
- }
- return "\@" . $array . $left . $list . $right;
-}
-
-sub pp_aslice { maybe_local(@_, slice(@_, "[", "]", "rv2av", "padav")) }
-sub pp_hslice { maybe_local(@_, slice(@_, "{", "}", "rv2hv", "padhv")) }
-
-sub pp_lslice {
- my $self = shift;
- my($op, $cx) = @_;
- my $idx = $op->first;
- my $list = $op->last;
- my(@elems, $kid);
- $list = $self->deparse($list, 1);
- $idx = $self->deparse($idx, 1);
- return "($list)" . "[$idx]";
-}
-
-sub want_scalar {
- my $op = shift;
- return ($op->flags & OPf_WANT) == OPf_WANT_SCALAR;
-}
-
-sub want_list {
- my $op = shift;
- return ($op->flags & OPf_WANT) == OPf_WANT_LIST;
-}
-
-sub method {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first->sibling; # skip pushmark
- my($meth, $obj, @exprs);
- if ($kid->name eq "list" and want_list $kid) {
- # When an indirect object isn't a bareword but the args are in
- # parens, the parens aren't part of the method syntax (the LLAFR
- # doesn't apply), but they make a list with OPf_PARENS set that
- # doesn't get flattened by the append_elem that adds the method,
- # making a (object, arg1, arg2, ...) list where the object
- # usually is. This can be distinguished from
- # `($obj, $arg1, $arg2)->meth()' (which is legal if $arg2 is an
- # object) because in the later the list is in scalar context
- # as the left side of -> always is, while in the former
- # the list is in list context as method arguments always are.
- # (Good thing there aren't method prototypes!)
- $meth = $kid->sibling;
- $kid = $kid->first->sibling; # skip pushmark
- $obj = $kid;
- $kid = $kid->sibling;
- for (; not null $kid; $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 6);
- }
- } else {
- $obj = $kid;
- $kid = $kid->sibling;
- for (; not null $kid->sibling; $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 6);
- }
- $meth = $kid;
- }
- $obj = $self->deparse($obj, 24);
- if ($meth->name eq "method_named") {
- $meth = $self->const_sv($meth)->PV;
- } else {
- $meth = $meth->first;
- if ($meth->name eq "const") {
- # As of 5.005_58, this case is probably obsoleted by the
- # method_named case above
- $meth = $self->const_sv($meth)->PV; # needs to be bare
- } else {
- $meth = $self->deparse($meth, 1);
- }
- }
- my $args = join(", ", @exprs);
- $kid = $obj . "->" . $meth;
- if ($args) {
- return $kid . "(" . $args . ")"; # parens mandatory
- } else {
- return $kid;
- }
-}
-
-# returns "&" if the prototype doesn't match the args,
-# or ("", $args_after_prototype_demunging) if it does.
-sub check_proto {
- my $self = shift;
- my($proto, @args) = @_;
- my($arg, $real);
- my $doneok = 0;
- my @reals;
- # An unbackslashed @ or % gobbles up the rest of the args
- $proto =~ s/([^\\]|^)([@%])(.*)$/$1$2/;
- while ($proto) {
- $proto =~ s/^ *([\\]?[\$\@&%*]|;)//;
- my $chr = $1;
- if ($chr eq "") {
- return "&" if @args;
- } elsif ($chr eq ";") {
- $doneok = 1;
- } elsif ($chr eq "@" or $chr eq "%") {
- push @reals, map($self->deparse($_, 6), @args);
- @args = ();
- } else {
- $arg = shift @args;
- last unless $arg;
- if ($chr eq "\$") {
- if (want_scalar $arg) {
- push @reals, $self->deparse($arg, 6);
- } else {
- return "&";
- }
- } elsif ($chr eq "&") {
- if ($arg->name =~ /^(s?refgen|undef)$/) {
- push @reals, $self->deparse($arg, 6);
- } else {
- return "&";
- }
- } elsif ($chr eq "*") {
- if ($arg->name =~ /^s?refgen$/
- and $arg->first->first->name eq "rv2gv")
- {
- $real = $arg->first->first; # skip refgen, null
- if ($real->first->name eq "gv") {
- push @reals, $self->deparse($real, 6);
- } else {
- push @reals, $self->deparse($real->first, 6);
- }
- } else {
- return "&";
- }
- } elsif (substr($chr, 0, 1) eq "\\") {
- $chr = substr($chr, 1);
- if ($arg->name =~ /^s?refgen$/ and
- !null($real = $arg->first) and
- ($chr eq "\$" && is_scalar($real->first)
- or ($chr eq "\@"
- && $real->first->sibling->name
- =~ /^(rv2|pad)av$/)
- or ($chr eq "%"
- && $real->first->sibling->name
- =~ /^(rv2|pad)hv$/)
- #or ($chr eq "&" # This doesn't work
- # && $real->first->name eq "rv2cv")
- or ($chr eq "*"
- && $real->first->name eq "rv2gv")))
- {
- push @reals, $self->deparse($real, 6);
- } else {
- return "&";
- }
- }
- }
- }
- return "&" if $proto and !$doneok; # too few args and no `;'
- return "&" if @args; # too many args
- return ("", join ", ", @reals);
-}
-
-sub pp_entersub {
- my $self = shift;
- my($op, $cx) = @_;
- return $self->method($op, $cx) unless null $op->first->sibling;
- my $prefix = "";
- my $amper = "";
- my($kid, @exprs);
- if ($op->flags & OPf_SPECIAL) {
- $prefix = "do ";
- } elsif ($op->private & OPpENTERSUB_AMPER) {
- $amper = "&";
- }
- $kid = $op->first;
- $kid = $kid->first->sibling; # skip ex-list, pushmark
- for (; not null $kid->sibling; $kid = $kid->sibling) {
- push @exprs, $kid;
- }
- my $simple = 0;
- my $proto = undef;
- if (is_scope($kid)) {
- $amper = "&";
- $kid = "{" . $self->deparse($kid, 0) . "}";
- } elsif ($kid->first->name eq "gv") {
- my $gv = $self->gv_or_padgv($kid->first);
- if (class($gv->CV) ne "SPECIAL") {
- $proto = $gv->CV->PV if $gv->CV->FLAGS & SVf_POK;
- }
- $simple = 1; # only calls of named functions can be prototyped
- $kid = $self->deparse($kid, 24);
- } elsif (is_scalar $kid->first) {
- $amper = "&";
- $kid = $self->deparse($kid, 24);
- } else {
- $prefix = "";
- my $arrow = is_subscriptable($kid->first) ? "" : "->";
- $kid = $self->deparse($kid, 24) . $arrow;
- }
- my $args;
- if (defined $proto and not $amper) {
- ($amper, $args) = $self->check_proto($proto, @exprs);
- if ($amper eq "&") {
- $args = join(", ", map($self->deparse($_, 6), @exprs));
- }
- } else {
- $args = join(", ", map($self->deparse($_, 6), @exprs));
- }
- if ($prefix or $amper) {
- if ($op->flags & OPf_STACKED) {
- return $prefix . $amper . $kid . "(" . $args . ")";
- } else {
- return $prefix . $amper. $kid;
- }
- } else {
- if (defined $proto and $proto eq "") {
- return $kid;
- } elsif (defined $proto and $proto eq "\$") {
- return $self->maybe_parens_func($kid, $args, $cx, 16);
- } elsif (defined($proto) && $proto or $simple) {
- return $self->maybe_parens_func($kid, $args, $cx, 5);
- } else {
- return "$kid(" . $args . ")";
- }
- }
-}
-
-sub pp_enterwrite { unop(@_, "write") }
-
-# escape things that cause interpolation in double quotes,
-# but not character escapes
-sub uninterp {
- my($str) = @_;
- $str =~ s/(^|[^\\])([\$\@]|\\[uUlLQE])/$1\\$2/g;
- return $str;
-}
-
-# the same, but treat $|, $), and $ at the end of the string differently
-sub re_uninterp {
- my($str) = @_;
- $str =~ s/(^|[^\\])(\@|\\[uUlLQE])/$1\\$2/g;
- $str =~ s/(^|[^\\])(\$[^)|])/$1\\$2/g;
- return $str;
-}
-
-# character escapes, but not delimiters that might need to be escaped
-sub escape_str { # ASCII
- my($str) = @_;
- $str =~ s/\a/\\a/g;
-# $str =~ s/\cH/\\b/g; # \b means someting different in a regex
- $str =~ s/\t/\\t/g;
- $str =~ s/\n/\\n/g;
- $str =~ s/\e/\\e/g;
- $str =~ s/\f/\\f/g;
- $str =~ s/\r/\\r/g;
- $str =~ s/([\cA-\cZ])/'\\c' . chr(ord('@') + ord($1))/ge;
- $str =~ s/([\0\033-\037\177-\377])/'\\' . sprintf("%03o", ord($1))/ge;
- return $str;
-}
-
-# Don't do this for regexen
-sub unback {
- my($str) = @_;
- $str =~ s/\\/\\\\/g;
- return $str;
-}
-
-sub balanced_delim {
- my($str) = @_;
- my @str = split //, $str;
- my($ar, $open, $close, $fail, $c, $cnt);
- for $ar (['[',']'], ['(',')'], ['<','>'], ['{','}']) {
- ($open, $close) = @$ar;
- $fail = 0; $cnt = 0;
- for $c (@str) {
- if ($c eq $open) {
- $cnt++;
- } elsif ($c eq $close) {
- $cnt--;
- if ($cnt < 0) {
- # qq()() isn't ")("
- $fail = 1;
- last;
- }
- }
- }
- $fail = 1 if $cnt != 0;
- return ($open, "$open$str$close") if not $fail;
- }
- return ("", $str);
-}
-
-sub single_delim {
- my($q, $default, $str) = @_;
- return "$default$str$default" if $default and index($str, $default) == -1;
- my($succeed, $delim);
- ($succeed, $str) = balanced_delim($str);
- return "$q$str" if $succeed;
- for $delim ('/', '"', '#') {
- return "$q$delim" . $str . $delim if index($str, $delim) == -1;
- }
- if ($default) {
- $str =~ s/$default/\\$default/g;
- return "$default$str$default";
- } else {
- $str =~ s[/][\\/]g;
- return "$q/$str/";
- }
-}
-
-sub const {
- my $sv = shift;
- if (class($sv) eq "SPECIAL") {
- return ('undef', '1', '0')[$$sv-1]; # sv_undef, sv_yes, sv_no
- } elsif ($sv->FLAGS & SVf_IOK) {
- return $sv->int_value;
- } elsif ($sv->FLAGS & SVf_NOK) {
- return $sv->NV;
- } elsif ($sv->FLAGS & SVf_ROK) {
- return "\\(" . const($sv->RV) . ")"; # constant folded
- } else {
- my $str = $sv->PV;
- if ($str =~ /[^ -~]/) { # ASCII for non-printing
- return single_delim("qq", '"', uninterp escape_str unback $str);
- } else {
- return single_delim("q", "'", unback $str);
- }
- }
-}
-
-sub const_sv {
- my $self = shift;
- my $op = shift;
- my $sv = $op->sv;
- # the constant could be in the pad (under useithreads)
- $sv = $self->padval($op->targ) unless $$sv;
- return $sv;
-}
-
-sub pp_const {
- my $self = shift;
- my($op, $cx) = @_;
-# if ($op->private & OPpCONST_BARE) { # trouble with `=>' autoquoting
-# return $self->const_sv($op)->PV;
-# }
- my $sv = $self->const_sv($op);
-# return const($sv);
- my $c = const $sv;
- return $c =~ /^-\d/ ? $self->maybe_parens($c, $cx, 21) : $c;
-}
-
-sub dq {
- my $self = shift;
- my $op = shift;
- my $type = $op->name;
- if ($type eq "const") {
- return uninterp(escape_str(unback($self->const_sv($op)->PV)));
- } elsif ($type eq "concat") {
- my $first = $self->dq($op->first);
- my $last = $self->dq($op->last);
- # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]"
- if ($last =~ /^[{\[\w]/) {
- $first =~ s/([%\$@])([A-Za-z_]\w*)$/${1}{$2}/;
- }
- return $first . $last;
- } elsif ($type eq "uc") {
- return '\U' . $self->dq($op->first->sibling) . '\E';
- } elsif ($type eq "lc") {
- return '\L' . $self->dq($op->first->sibling) . '\E';
- } elsif ($type eq "ucfirst") {
- return '\u' . $self->dq($op->first->sibling);
- } elsif ($type eq "lcfirst") {
- return '\l' . $self->dq($op->first->sibling);
- } elsif ($type eq "quotemeta") {
- return '\Q' . $self->dq($op->first->sibling) . '\E';
- } elsif ($type eq "join") {
- return $self->deparse($op->last, 26); # was join($", @ary)
- } else {
- return $self->deparse($op, 26);
- }
-}
-
-sub pp_backtick {
- my $self = shift;
- my($op, $cx) = @_;
- # skip pushmark
- return single_delim("qx", '`', $self->dq($op->first->sibling));
-}
-
-sub dquote {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first->sibling; # skip ex-stringify, pushmark
- return $self->deparse($kid, $cx) if $self->{'unquote'};
- $self->maybe_targmy($kid, $cx,
- sub {single_delim("qq", '"', $self->dq($_[1]))});
-}
-
-# OP_STRINGIFY is a listop, but it only ever has one arg
-sub pp_stringify { maybe_targmy(@_, \&dquote) }
-
-# tr/// and s/// (and tr[][], tr[]//, tr###, etc)
-# note that tr(from)/to/ is OK, but not tr/from/(to)
-sub double_delim {
- my($from, $to) = @_;
- my($succeed, $delim);
- if ($from !~ m[/] and $to !~ m[/]) {
- return "/$from/$to/";
- } elsif (($succeed, $from) = balanced_delim($from) and $succeed) {
- if (($succeed, $to) = balanced_delim($to) and $succeed) {
- return "$from$to";
- } else {
- for $delim ('/', '"', '#') { # note no `'' -- s''' is special
- return "$from$delim$to$delim" if index($to, $delim) == -1;
- }
- $to =~ s[/][\\/]g;
- return "$from/$to/";
- }
- } else {
- for $delim ('/', '"', '#') { # note no '
- return "$delim$from$delim$to$delim"
- if index($to . $from, $delim) == -1;
- }
- $from =~ s[/][\\/]g;
- $to =~ s[/][\\/]g;
- return "/$from/$to/";
- }
-}
-
-sub pchr { # ASCII
- my($n) = @_;
- if ($n == ord '\\') {
- return '\\\\';
- } elsif ($n >= ord(' ') and $n <= ord('~')) {
- return chr($n);
- } elsif ($n == ord "\a") {
- return '\\a';
- } elsif ($n == ord "\b") {
- return '\\b';
- } elsif ($n == ord "\t") {
- return '\\t';
- } elsif ($n == ord "\n") {
- return '\\n';
- } elsif ($n == ord "\e") {
- return '\\e';
- } elsif ($n == ord "\f") {
- return '\\f';
- } elsif ($n == ord "\r") {
- return '\\r';
- } elsif ($n >= ord("\cA") and $n <= ord("\cZ")) {
- return '\\c' . chr(ord("@") + $n);
- } else {
-# return '\x' . sprintf("%02x", $n);
- return '\\' . sprintf("%03o", $n);
- }
-}
-
-sub collapse {
- my(@chars) = @_;
- my($str, $c, $tr) = ("");
- for ($c = 0; $c < @chars; $c++) {
- $tr = $chars[$c];
- $str .= pchr($tr);
- if ($c <= $#chars - 2 and $chars[$c + 1] == $tr + 1 and
- $chars[$c + 2] == $tr + 2)
- {
- for (; $c <= $#chars-1 and $chars[$c + 1] == $chars[$c] + 1; $c++)
- {}
- $str .= "-";
- $str .= pchr($chars[$c]);
- }
- }
- return $str;
-}
-
-# XXX This has trouble with hyphens in the replacement (tr/bac/-AC/),
-# and backslashes.
-
-sub tr_decode_byte {
- my($table, $flags) = @_;
- my(@table) = unpack("s256", $table);
- my($c, $tr, @from, @to, @delfrom, $delhyphen);
- if ($table[ord "-"] != -1 and
- $table[ord("-") - 1] == -1 || $table[ord("-") + 1] == -1)
- {
- $tr = $table[ord "-"];
- $table[ord "-"] = -1;
- if ($tr >= 0) {
- @from = ord("-");
- @to = $tr;
- } else { # -2 ==> delete
- $delhyphen = 1;
- }
- }
- for ($c = 0; $c < 256; $c++) {
- $tr = $table[$c];
- if ($tr >= 0) {
- push @from, $c; push @to, $tr;
- } elsif ($tr == -2) {
- push @delfrom, $c;
- }
- }
- @from = (@from, @delfrom);
- if ($flags & OPpTRANS_COMPLEMENT) {
- my @newfrom = ();
- my %from;
- @from{@from} = (1) x @from;
- for ($c = 0; $c < 256; $c++) {
- push @newfrom, $c unless $from{$c};
- }
- @from = @newfrom;
- }
- unless ($flags & OPpTRANS_DELETE || !@to) {
- pop @to while $#to and $to[$#to] == $to[$#to -1];
- }
- my($from, $to);
- $from = collapse(@from);
- $to = collapse(@to);
- $from .= "-" if $delhyphen;
- return ($from, $to);
-}
-
-sub tr_chr {
- my $x = shift;
- if ($x == ord "-") {
- return "\\-";
- } else {
- return chr $x;
- }
-}
-
-# XXX This doesn't yet handle all cases correctly either
-
-sub tr_decode_utf8 {
- my($swash_hv, $flags) = @_;
- my %swash = $swash_hv->ARRAY;
- my $final = undef;
- $final = $swash{'FINAL'}->IV if exists $swash{'FINAL'};
- my $none = $swash{"NONE"}->IV;
- my $extra = $none + 1;
- my(@from, @delfrom, @to);
- my $line;
- foreach $line (split /\n/, $swash{'LIST'}->PV) {
- my($min, $max, $result) = split(/\t/, $line);
- $min = hex $min;
- if (length $max) {
- $max = hex $max;
- } else {
- $max = $min;
- }
- $result = hex $result;
- if ($result == $extra) {
- push @delfrom, [$min, $max];
- } else {
- push @from, [$min, $max];
- push @to, [$result, $result + $max - $min];
- }
- }
- for my $i (0 .. $#from) {
- if ($from[$i][0] == ord '-') {
- unshift @from, splice(@from, $i, 1);
- unshift @to, splice(@to, $i, 1);
- last;
- } elsif ($from[$i][1] == ord '-') {
- $from[$i][1]--;
- $to[$i][1]--;
- unshift @from, ord '-';
- unshift @to, ord '-';
- last;
- }
- }
- for my $i (0 .. $#delfrom) {
- if ($delfrom[$i][0] == ord '-') {
- push @delfrom, splice(@delfrom, $i, 1);
- last;
- } elsif ($delfrom[$i][1] == ord '-') {
- $delfrom[$i][1]--;
- push @delfrom, ord '-';
- last;
- }
- }
- if (defined $final and $to[$#to][1] != $final) {
- push @to, [$final, $final];
- }
- push @from, @delfrom;
- if ($flags & OPpTRANS_COMPLEMENT) {
- my @newfrom;
- my $next = 0;
- for my $i (0 .. $#from) {
- push @newfrom, [$next, $from[$i][0] - 1];
- $next = $from[$i][1] + 1;
- }
- @from = ();
- for my $range (@newfrom) {
- if ($range->[0] <= $range->[1]) {
- push @from, $range;
- }
- }
- }
- my($from, $to, $diff);
- for my $chunk (@from) {
- $diff = $chunk->[1] - $chunk->[0];
- if ($diff > 1) {
- $from .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
- } elsif ($diff == 1) {
- $from .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
- } else {
- $from .= tr_chr($chunk->[0]);
- }
- }
- for my $chunk (@to) {
- $diff = $chunk->[1] - $chunk->[0];
- if ($diff > 1) {
- $to .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
- } elsif ($diff == 1) {
- $to .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
- } else {
- $to .= tr_chr($chunk->[0]);
- }
- }
- #$final = sprintf("%04x", $final) if defined $final;
- #$none = sprintf("%04x", $none) if defined $none;
- #$extra = sprintf("%04x", $extra) if defined $extra;
- #print STDERR "final: $final\n none: $none\nextra: $extra\n";
- #print STDERR $swash{'LIST'}->PV;
- return (escape_str($from), escape_str($to));
-}
-
-sub pp_trans {
- my $self = shift;
- my($op, $cx) = @_;
- my($from, $to);
- if (class($op) eq "PVOP") {
- ($from, $to) = tr_decode_byte($op->pv, $op->private);
- } else { # class($op) eq "SVOP"
- ($from, $to) = tr_decode_utf8($op->sv->RV, $op->private);
- }
- my $flags = "";
- $flags .= "c" if $op->private & OPpTRANS_COMPLEMENT;
- $flags .= "d" if $op->private & OPpTRANS_DELETE;
- $to = "" if $from eq $to and $flags eq "";
- $flags .= "s" if $op->private & OPpTRANS_SQUASH;
- return "tr" . double_delim($from, $to) . $flags;
-}
-
-# Like dq(), but different
-sub re_dq {
- my $self = shift;
- my $op = shift;
- my $type = $op->name;
- if ($type eq "const") {
- return re_uninterp($self->const_sv($op)->PV);
- } elsif ($type eq "concat") {
- my $first = $self->re_dq($op->first);
- my $last = $self->re_dq($op->last);
- # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]"
- if ($last =~ /^[{\[\w]/) {
- $first =~ s/([%\$@])([A-Za-z_]\w*)$/${1}{$2}/;
- }
- return $first . $last;
- } elsif ($type eq "uc") {
- return '\U' . $self->re_dq($op->first->sibling) . '\E';
- } elsif ($type eq "lc") {
- return '\L' . $self->re_dq($op->first->sibling) . '\E';
- } elsif ($type eq "ucfirst") {
- return '\u' . $self->re_dq($op->first->sibling);
- } elsif ($type eq "lcfirst") {
- return '\l' . $self->re_dq($op->first->sibling);
- } elsif ($type eq "quotemeta") {
- return '\Q' . $self->re_dq($op->first->sibling) . '\E';
- } elsif ($type eq "join") {
- return $self->deparse($op->last, 26); # was join($", @ary)
- } else {
- return $self->deparse($op, 26);
- }
-}
-
-sub pp_regcomp {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first;
- $kid = $kid->first if $kid->name eq "regcmaybe";
- $kid = $kid->first if $kid->name eq "regcreset";
- return $self->re_dq($kid);
-}
-
-# osmic acid -- see osmium tetroxide
-
-my %matchwords;
-map($matchwords{join "", sort split //, $_} = $_, 'cig', 'cog', 'cos', 'cogs',
- 'cox', 'go', 'is', 'ism', 'iso', 'mig', 'mix', 'osmic', 'ox', 'sic',
- 'sig', 'six', 'smog', 'so', 'soc', 'sog', 'xi');
-
-sub matchop {
- my $self = shift;
- my($op, $cx, $name, $delim) = @_;
- my $kid = $op->first;
- my ($binop, $var, $re) = ("", "", "");
- if ($op->flags & OPf_STACKED) {
- $binop = 1;
- $var = $self->deparse($kid, 20);
- $kid = $kid->sibling;
- }
- if (null $kid) {
- $re = re_uninterp(escape_str($op->precomp));
- } else {
- $re = $self->deparse($kid, 1);
- }
- my $flags = "";
- $flags .= "c" if $op->pmflags & PMf_CONTINUE;
- $flags .= "g" if $op->pmflags & PMf_GLOBAL;
- $flags .= "i" if $op->pmflags & PMf_FOLD;
- $flags .= "m" if $op->pmflags & PMf_MULTILINE;
- $flags .= "o" if $op->pmflags & PMf_KEEP;
- $flags .= "s" if $op->pmflags & PMf_SINGLELINE;
- $flags .= "x" if $op->pmflags & PMf_EXTENDED;
- $flags = $matchwords{$flags} if $matchwords{$flags};
- if ($op->pmflags & PMf_ONCE) { # only one kind of delimiter works here
- $re =~ s/\?/\\?/g;
- $re = "?$re?";
- } else {
- $re = single_delim($name, $delim, $re);
- }
- $re = $re . $flags;
- if ($binop) {
- return $self->maybe_parens("$var =~ $re", $cx, 20);
- } else {
- return $re;
- }
-}
-
-sub pp_match { matchop(@_, "m", "/") }
-sub pp_pushre { matchop(@_, "m", "/") }
-sub pp_qr { matchop(@_, "qr", "") }
-
-sub pp_split {
- my $self = shift;
- my($op, $cx) = @_;
- my($kid, @exprs, $ary, $expr);
- $kid = $op->first;
- if ($ {$kid->pmreplroot}) {
- $ary = '@' . $self->gv_name($kid->pmreplroot);
- }
- for (; !null($kid); $kid = $kid->sibling) {
- push @exprs, $self->deparse($kid, 6);
- }
- $expr = "split(" . join(", ", @exprs) . ")";
- if ($ary) {
- return $self->maybe_parens("$ary = $expr", $cx, 7);
- } else {
- return $expr;
- }
-}
-
-# oxime -- any of various compounds obtained chiefly by the action of
-# hydroxylamine on aldehydes and ketones and characterized by the
-# bivalent grouping C=NOH [Webster's Tenth]
-
-my %substwords;
-map($substwords{join "", sort split //, $_} = $_, 'ego', 'egoism', 'em',
- 'es', 'ex', 'exes', 'gee', 'go', 'goes', 'ie', 'ism', 'iso', 'me',
- 'meese', 'meso', 'mig', 'mix', 'os', 'ox', 'oxime', 'see', 'seem',
- 'seg', 'sex', 'sig', 'six', 'smog', 'sog', 'some', 'xi');
-
-sub pp_subst {
- my $self = shift;
- my($op, $cx) = @_;
- my $kid = $op->first;
- my($binop, $var, $re, $repl) = ("", "", "", "");
- if ($op->flags & OPf_STACKED) {
- $binop = 1;
- $var = $self->deparse($kid, 20);
- $kid = $kid->sibling;
- }
- my $flags = "";
- if (null($op->pmreplroot)) {
- $repl = $self->dq($kid);
- $kid = $kid->sibling;
- } else {
- $repl = $op->pmreplroot->first; # skip substcont
- while ($repl->name eq "entereval") {
- $repl = $repl->first;
- $flags .= "e";
- }
- if ($op->pmflags & PMf_EVAL) {
- $repl = $self->deparse($repl, 0);
- } else {
- $repl = $self->dq($repl);
- }
- }
- if (null $kid) {
- $re = re_uninterp(escape_str($op->precomp));
- } else {
- $re = $self->deparse($kid, 1);
- }
- $flags .= "e" if $op->pmflags & PMf_EVAL;
- $flags .= "g" if $op->pmflags & PMf_GLOBAL;
- $flags .= "i" if $op->pmflags & PMf_FOLD;
- $flags .= "m" if $op->pmflags & PMf_MULTILINE;
- $flags .= "o" if $op->pmflags & PMf_KEEP;
- $flags .= "s" if $op->pmflags & PMf_SINGLELINE;
- $flags .= "x" if $op->pmflags & PMf_EXTENDED;
- $flags = $substwords{$flags} if $substwords{$flags};
- if ($binop) {
- return $self->maybe_parens("$var =~ s"
- . double_delim($re, $repl) . $flags,
- $cx, 20);
- } else {
- return "s". double_delim($re, $repl) . $flags;
- }
-}
-
-1;
-__END__
-
-=head1 NAME
-
-B::Deparse - Perl compiler backend to produce perl code
-
-=head1 SYNOPSIS
-
-B<perl> B<-MO=Deparse>[B<,-u>I<PACKAGE>][B<,-p>][B<,-q>][B<,-l>]
- [B<,-s>I<LETTERS>][B<,-x>I<LEVEL>] I<prog.pl>
-
-=head1 DESCRIPTION
-
-B::Deparse is a backend module for the Perl compiler that generates
-perl source code, based on the internal compiled structure that perl
-itself creates after parsing a program. The output of B::Deparse won't
-be exactly the same as the original source, since perl doesn't keep
-track of comments or whitespace, and there isn't a one-to-one
-correspondence between perl's syntactical constructions and their
-compiled form, but it will often be close. When you use the B<-p>
-option, the output also includes parentheses even when they are not
-required by precedence, which can make it easy to see if perl is
-parsing your expressions the way you intended.
-
-Please note that this module is mainly new and untested code and is
-still under development, so it may change in the future.
-
-=head1 OPTIONS
-
-As with all compiler backend options, these must follow directly after
-the '-MO=Deparse', separated by a comma but not any white space.
-
-=over 4
-
-=item B<-l>
-
-Add '#line' declarations to the output based on the line and file
-locations of the original code.
-
-=item B<-p>
-
-Print extra parentheses. Without this option, B::Deparse includes
-parentheses in its output only when they are needed, based on the
-structure of your program. With B<-p>, it uses parentheses (almost)
-whenever they would be legal. This can be useful if you are used to
-LISP, or if you want to see how perl parses your input. If you say
-
- if ($var & 0x7f == 65) {print "Gimme an A!"}
- print ($which ? $a : $b), "\n";
- $name = $ENV{USER} or "Bob";
-
-C<B::Deparse,-p> will print
-
- if (($var & 0)) {
- print('Gimme an A!')
- };
- (print(($which ? $a : $b)), '???');
- (($name = $ENV{'USER'}) or '???')
-
-which probably isn't what you intended (the C<'???'> is a sign that
-perl optimized away a constant value).
-
-=item B<-q>
-
-Expand double-quoted strings into the corresponding combinations of
-concatenation, uc, ucfirst, lc, lcfirst, quotemeta, and join. For
-instance, print
-
- print "Hello, $world, @ladies, \u$gentlemen\E, \u\L$me!";
-
-as
-
- print 'Hello, ' . $world . ', ' . join($", @ladies) . ', '
- . ucfirst($gentlemen) . ', ' . ucfirst(lc $me . '!');
-
-Note that the expanded form represents the way perl handles such
-constructions internally -- this option actually turns off the reverse
-translation that B::Deparse usually does. On the other hand, note that
-C<$x = "$y"> is not the same as C<$x = $y>: the former makes the value
-of $y into a string before doing the assignment.
-
-=item B<-u>I<PACKAGE>
-
-Normally, B::Deparse deparses the main code of a program, all the subs
-called by the main program (and all the subs called by them,
-recursively), and any other subs in the main:: package. To include
-subs in other packages that aren't called directly, such as AUTOLOAD,
-DESTROY, other subs called automatically by perl, and methods (which
-aren't resolved to subs until runtime), use the B<-u> option. The
-argument to B<-u> is the name of a package, and should follow directly
-after the 'u'. Multiple B<-u> options may be given, separated by
-commas. Note that unlike some other backends, B::Deparse doesn't
-(yet) try to guess automatically when B<-u> is needed -- you must
-invoke it yourself.
-
-=item B<-s>I<LETTERS>
-
-Tweak the style of B::Deparse's output. The letters should follow
-directly after the 's', with no space or punctuation. The following
-options are available:
-
-=over 4
-
-=item B<C>
-
-Cuddle C<elsif>, C<else>, and C<continue> blocks. For example, print
-
- if (...) {
- ...
- } else {
- ...
- }
-
-instead of
-
- if (...) {
- ...
- }
- else {
- ...
- }
-
-The default is not to cuddle.
-
-=item B<i>I<NUMBER>
-
-Indent lines by multiples of I<NUMBER> columns. The default is 4 columns.
-
-=item B<T>
-
-Use tabs for each 8 columns of indent. The default is to use only spaces.
-For instance, if the style options are B<-si4T>, a line that's indented
-3 times will be preceded by one tab and four spaces; if the options were
-B<-si8T>, the same line would be preceded by three tabs.
-
-=item B<v>I<STRING>B<.>
-
-Print I<STRING> for the value of a constant that can't be determined
-because it was optimized away (mnemonic: this happens when a constant
-is used in B<v>oid context). The end of the string is marked by a period.
-The string should be a valid perl expression, generally a constant.
-Note that unless it's a number, it probably needs to be quoted, and on
-a command line quotes need to be protected from the shell. Some
-conventional values include 0, 1, 42, '', 'foo', and
-'Useless use of constant omitted' (which may need to be
-B<-sv"'Useless use of constant omitted'.">
-or something similar depending on your shell). The default is '???'.
-If you're using B::Deparse on a module or other file that's require'd,
-you shouldn't use a value that evaluates to false, since the customary
-true constant at the end of a module will be in void context when the
-file is compiled as a main program.
-
-=back
-
-=item B<-x>I<LEVEL>
-
-Expand conventional syntax constructions into equivalent ones that expose
-their internal operation. I<LEVEL> should be a digit, with higher values
-meaning more expansion. As with B<-q>, this actually involves turning off
-special cases in B::Deparse's normal operations.
-
-If I<LEVEL> is at least 3, for loops will be translated into equivalent
-while loops with continue blocks; for instance
-
- for ($i = 0; $i < 10; ++$i) {
- print $i;
- }
-
-turns into
-
- $i = 0;
- while ($i < 10) {
- print $i;
- } continue {
- ++$i
- }
-
-Note that in a few cases this translation can't be perfectly carried back
-into the source code -- if the loop's initializer declares a my variable,
-for instance, it won't have the correct scope outside of the loop.
-
-If I<LEVEL> is at least 7, if statements will be translated into equivalent
-expressions using C<&&>, C<?:> and C<do {}>; for instance
-
- print 'hi' if $nice;
- if ($nice) {
- print 'hi';
- }
- if ($nice) {
- print 'hi';
- } else {
- print 'bye';
- }
-
-turns into
-
- $nice and print 'hi';
- $nice and do { print 'hi' };
- $nice ? do { print 'hi' } : do { print 'bye' };
-
-Long sequences of elsifs will turn into nested ternary operators, which
-B::Deparse doesn't know how to indent nicely.
-
-=back
-
-=head1 USING B::Deparse AS A MODULE
-
-=head2 Synopsis
-
- use B::Deparse;
- $deparse = B::Deparse->new("-p", "-sC");
- $body = $deparse->coderef2text(\&func);
- eval "sub func $body"; # the inverse operation
-
-=head2 Description
-
-B::Deparse can also be used on a sub-by-sub basis from other perl
-programs.
-
-=head2 new
-
- $deparse = B::Deparse->new(OPTIONS)
-
-Create an object to store the state of a deparsing operation and any
-options. The options are the same as those that can be given on the
-command line (see L</OPTIONS>); options that are separated by commas
-after B<-MO=Deparse> should be given as separate strings. Some
-options, like B<-u>, don't make sense for a single subroutine, so
-don't pass them.
-
-=head2 coderef2text
-
- $body = $deparse->coderef2text(\&func)
- $body = $deparse->coderef2text(sub ($$) { ... })
-
-Return source code for the body of a subroutine (a block, optionally
-preceded by a prototype in parens), given a reference to the
-sub. Because a subroutine can have no names, or more than one name,
-this method doesn't return a complete subroutine definition -- if you
-want to eval the result, you should prepend "sub subname ", or "sub "
-for an anonymous function constructor. Unless the sub was defined in
-the main:: package, the code will include a package declaration.
-
-=head1 BUGS
-
-See the 'to do' list at the beginning of the module file.
-
-=head1 AUTHOR
-
-Stephen McCamant <smcc@CSUA.Berkeley.EDU>, based on an earlier
-version by Malcolm Beattie <mbeattie@sable.ox.ac.uk>, with
-contributions from Gisle Aas, James Duncan, Albert Dvornik, Hugo van
-der Sanden, Gurusamy Sarathy, and Nick Ing-Simmons.
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Disassembler.pm b/contrib/perl5/ext/B/B/Disassembler.pm
deleted file mode 100644
index 212532b..0000000
--- a/contrib/perl5/ext/B/B/Disassembler.pm
+++ /dev/null
@@ -1,185 +0,0 @@
-# Disassembler.pm
-#
-# Copyright (c) 1996 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::Disassembler::BytecodeStream;
-use FileHandle;
-use Carp;
-use B qw(cstring cast_I32);
-@ISA = qw(FileHandle);
-sub readn {
- my ($fh, $len) = @_;
- my $data;
- read($fh, $data, $len);
- croak "reached EOF while reading $len bytes" unless length($data) == $len;
- return $data;
-}
-
-sub GET_U8 {
- my $fh = shift;
- my $c = $fh->getc;
- croak "reached EOF while reading U8" unless defined($c);
- return ord($c);
-}
-
-sub GET_U16 {
- my $fh = shift;
- my $str = $fh->readn(2);
- croak "reached EOF while reading U16" unless length($str) == 2;
- return unpack("n", $str);
-}
-
-sub GET_NV {
- my $fh = shift;
- my $str = $fh->readn(8);
- croak "reached EOF while reading NV" unless length($str) == 8;
- return unpack("N", $str);
-}
-
-sub GET_U32 {
- my $fh = shift;
- my $str = $fh->readn(4);
- croak "reached EOF while reading U32" unless length($str) == 4;
- return unpack("N", $str);
-}
-
-sub GET_I32 {
- my $fh = shift;
- my $str = $fh->readn(4);
- croak "reached EOF while reading I32" unless length($str) == 4;
- return cast_I32(unpack("N", $str));
-}
-
-sub GET_objindex {
- my $fh = shift;
- my $str = $fh->readn(4);
- croak "reached EOF while reading objindex" unless length($str) == 4;
- return unpack("N", $str);
-}
-
-sub GET_opindex {
- my $fh = shift;
- my $str = $fh->readn(4);
- croak "reached EOF while reading opindex" unless length($str) == 4;
- return unpack("N", $str);
-}
-
-sub GET_svindex {
- my $fh = shift;
- my $str = $fh->readn(4);
- croak "reached EOF while reading svindex" unless length($str) == 4;
- return unpack("N", $str);
-}
-
-sub GET_strconst {
- my $fh = shift;
- my ($str, $c);
- while (defined($c = $fh->getc) && $c ne "\0") {
- $str .= $c;
- }
- croak "reached EOF while reading strconst" unless defined($c);
- return cstring($str);
-}
-
-sub GET_pvcontents {}
-
-sub GET_PV {
- my $fh = shift;
- my $str;
- my $len = $fh->GET_U32;
- if ($len) {
- read($fh, $str, $len);
- croak "reached EOF while reading PV" unless length($str) == $len;
- return cstring($str);
- } else {
- return '""';
- }
-}
-
-sub GET_comment_t {
- my $fh = shift;
- my ($str, $c);
- while (defined($c = $fh->getc) && $c ne "\n") {
- $str .= $c;
- }
- croak "reached EOF while reading comment" unless defined($c);
- return cstring($str);
-}
-
-sub GET_double {
- my $fh = shift;
- my ($str, $c);
- while (defined($c = $fh->getc) && $c ne "\0") {
- $str .= $c;
- }
- croak "reached EOF while reading double" unless defined($c);
- return $str;
-}
-
-sub GET_none {}
-
-sub GET_op_tr_array {
- my $fh = shift;
- my @ary = unpack("n256", $fh->readn(256 * 2));
- return join(",", @ary);
-}
-
-sub GET_IV64 {
- my $fh = shift;
- my ($hi, $lo) = unpack("NN", $fh->readn(8));
- return sprintf("0x%4x%04x", $hi, $lo); # cheat
-}
-
-package B::Disassembler;
-use Exporter;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(disassemble_fh);
-use Carp;
-use strict;
-
-use B::Asmdata qw(%insn_data @insn_name);
-
-sub disassemble_fh {
- my ($fh, $out) = @_;
- my ($c, $getmeth, $insn, $arg);
- bless $fh, "B::Disassembler::BytecodeStream";
- while (defined($c = $fh->getc)) {
- $c = ord($c);
- $insn = $insn_name[$c];
- if (!defined($insn) || $insn eq "unused") {
- my $pos = $fh->tell - 1;
- die "Illegal instruction code $c at stream offset $pos\n";
- }
- $getmeth = $insn_data{$insn}->[2];
- $arg = $fh->$getmeth();
- if (defined($arg)) {
- &$out($insn, $arg);
- } else {
- &$out($insn);
- }
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Disassembler - Disassemble Perl bytecode
-
-=head1 SYNOPSIS
-
- use Disassembler;
-
-=head1 DESCRIPTION
-
-See F<ext/B/B/Disassembler.pm>.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Lint.pm b/contrib/perl5/ext/B/B/Lint.pm
deleted file mode 100644
index 094b3cf..0000000
--- a/contrib/perl5/ext/B/B/Lint.pm
+++ /dev/null
@@ -1,362 +0,0 @@
-package B::Lint;
-
-=head1 NAME
-
-B::Lint - Perl lint
-
-=head1 SYNOPSIS
-
-perl -MO=Lint[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-The B::Lint module is equivalent to an extended version of the B<-w>
-option of B<perl>. It is named after the program B<lint> which carries
-out a similar process for C programs.
-
-=head1 OPTIONS AND LINT CHECKS
-
-Option words are separated by commas (not whitespace) and follow the
-usual conventions of compiler backend options. Following any options
-(indicated by a leading B<->) come lint check arguments. Each such
-argument (apart from the special B<all> and B<none> options) is a
-word representing one possible lint check (turning on that check) or
-is B<no-foo> (turning off that check). Before processing the check
-arguments, a standard list of checks is turned on. Later options
-override earlier ones. Available options are:
-
-=over 8
-
-=item B<context>
-
-Produces a warning whenever an array is used in an implicit scalar
-context. For example, both of the lines
-
- $foo = length(@bar);
- $foo = @bar;
-will elicit a warning. Using an explicit B<scalar()> silences the
-warning. For example,
-
- $foo = scalar(@bar);
-
-=item B<implicit-read> and B<implicit-write>
-
-These options produce a warning whenever an operation implicitly
-reads or (respectively) writes to one of Perl's special variables.
-For example, B<implicit-read> will warn about these:
-
- /foo/;
-
-and B<implicit-write> will warn about these:
-
- s/foo/bar/;
-
-Both B<implicit-read> and B<implicit-write> warn about this:
-
- for (@a) { ... }
-
-=item B<dollar-underscore>
-
-This option warns whenever $_ is used either explicitly anywhere or
-as the implicit argument of a B<print> statement.
-
-=item B<private-names>
-
-This option warns on each use of any variable, subroutine or
-method name that lives in a non-current package but begins with
-an underscore ("_"). Warnings aren't issued for the special case
-of the single character name "_" by itself (e.g. $_ and @_).
-
-=item B<undefined-subs>
-
-This option warns whenever an undefined subroutine is invoked.
-This option will only catch explicitly invoked subroutines such
-as C<foo()> and not indirect invocations such as C<&$subref()>
-or C<$obj-E<gt>meth()>. Note that some programs or modules delay
-definition of subs until runtime by means of the AUTOLOAD
-mechanism.
-
-=item B<regexp-variables>
-
-This option warns whenever one of the regexp variables $', $& or
-$' is used. Any occurrence of any of these variables in your
-program can slow your whole program down. See L<perlre> for
-details.
-
-=item B<all>
-
-Turn all warnings on.
-
-=item B<none>
-
-Turn all warnings off.
-
-=back
-
-=head1 NON LINT-CHECK OPTIONS
-
-=over 8
-
-=item B<-u Package>
-
-Normally, Lint only checks the main code of the program together
-with all subs defined in package main. The B<-u> option lets you
-include other package names whose subs are then checked by Lint.
-
-=back
-
-=head1 BUGS
-
-This is only a very preliminary version.
-
-=head1 AUTHOR
-
-Malcolm Beattie, mbeattie@sable.ox.ac.uk.
-
-=cut
-
-use strict;
-use B qw(walkoptree main_root walksymtable svref_2object parents
- OPf_WANT_LIST OPf_WANT OPf_STACKED G_ARRAY
- );
-
-my $file = "unknown"; # shadows current filename
-my $line = 0; # shadows current line number
-my $curstash = "main"; # shadows current stash
-
-# Lint checks
-my %check;
-my %implies_ok_context;
-BEGIN {
- map($implies_ok_context{$_}++,
- qw(scalar av2arylen aelem aslice helem hslice
- keys values hslice defined undef delete));
-}
-
-# Lint checks turned on by default
-my @default_checks = qw(context);
-
-my %valid_check;
-# All valid checks
-BEGIN {
- map($valid_check{$_}++,
- qw(context implicit_read implicit_write dollar_underscore
- private_names undefined_subs regexp_variables));
-}
-
-# Debugging options
-my ($debug_op);
-
-my %done_cv; # used to mark which subs have already been linted
-my @extra_packages; # Lint checks mainline code and all subs which are
- # in main:: or in one of these packages.
-
-sub warning {
- my $format = (@_ < 2) ? "%s" : shift;
- warn sprintf("$format at %s line %d\n", @_, $file, $line);
-}
-
-# This gimme can't cope with context that's only determined
-# at runtime via dowantarray().
-sub gimme {
- my $op = shift;
- my $flags = $op->flags;
- if ($flags & OPf_WANT) {
- return(($flags & OPf_WANT_LIST) ? 1 : 0);
- }
- return undef;
-}
-
-sub B::OP::lint {}
-
-sub B::COP::lint {
- my $op = shift;
- if ($op->name eq "nextstate") {
- $file = $op->file;
- $line = $op->line;
- $curstash = $op->stash->NAME;
- }
-}
-
-sub B::UNOP::lint {
- my $op = shift;
- my $opname = $op->name;
- if ($check{context} && ($opname eq "rv2av" || $opname eq "rv2hv")) {
- my $parent = parents->[0];
- my $pname = $parent->name;
- return if gimme($op) || $implies_ok_context{$pname};
- # Two special cases to deal with: "foreach (@foo)" and "delete $a{$b}"
- # null out the parent so we have to check for a parent of pp_null and
- # a grandparent of pp_enteriter or pp_delete
- if ($pname eq "null") {
- my $gpname = parents->[1]->name;
- return if $gpname eq "enteriter" || $gpname eq "delete";
- }
- warning("Implicit scalar context for %s in %s",
- $opname eq "rv2av" ? "array" : "hash", $parent->desc);
- }
- if ($check{private_names} && $opname eq "method") {
- my $methop = $op->first;
- if ($methop->name eq "const") {
- my $method = $methop->sv->PV;
- if ($method =~ /^_/ && !defined(&{"$curstash\::$method"})) {
- warning("Illegal reference to private method name $method");
- }
- }
- }
-}
-
-sub B::PMOP::lint {
- my $op = shift;
- if ($check{implicit_read}) {
- if ($op->name eq "match" && !($op->flags & OPf_STACKED)) {
- warning('Implicit match on $_');
- }
- }
- if ($check{implicit_write}) {
- if ($op->name eq "subst" && !($op->flags & OPf_STACKED)) {
- warning('Implicit substitution on $_');
- }
- }
-}
-
-sub B::LOOP::lint {
- my $op = shift;
- if ($check{implicit_read} || $check{implicit_write}) {
- if ($op->name eq "enteriter") {
- my $last = $op->last;
- if ($last->name eq "gv" && $last->gv->NAME eq "_") {
- warning('Implicit use of $_ in foreach');
- }
- }
- }
-}
-
-sub B::SVOP::lint {
- my $op = shift;
- if ($check{dollar_underscore} && $op->name eq "gvsv"
- && $op->gv->NAME eq "_")
- {
- warning('Use of $_');
- }
- if ($check{private_names}) {
- my $opname = $op->name;
- if ($opname eq "gv" || $opname eq "gvsv") {
- my $gv = $op->gv;
- if ($gv->NAME =~ /^_./ && $gv->STASH->NAME ne $curstash) {
- warning('Illegal reference to private name %s', $gv->NAME);
- }
- }
- }
- if ($check{undefined_subs}) {
- if ($op->name eq "gv"
- && $op->next->name eq "entersub")
- {
- my $gv = $op->gv;
- my $subname = $gv->STASH->NAME . "::" . $gv->NAME;
- no strict 'refs';
- if (!defined(&$subname)) {
- $subname =~ s/^main:://;
- warning('Undefined subroutine %s called', $subname);
- }
- }
- }
- if ($check{regexp_variables} && $op->name eq "gvsv") {
- my $name = $op->gv->NAME;
- if ($name =~ /^[&'`]$/) {
- warning('Use of regexp variable $%s', $name);
- }
- }
-}
-
-sub B::GV::lintcv {
- my $gv = shift;
- my $cv = $gv->CV;
- #warn sprintf("lintcv: %s::%s (done=%d)\n",
- # $gv->STASH->NAME, $gv->NAME, $done_cv{$$cv});#debug
- return if !$$cv || $done_cv{$$cv}++;
- my $root = $cv->ROOT;
- #warn " root = $root (0x$$root)\n";#debug
- walkoptree($root, "lint") if $$root;
-}
-
-sub do_lint {
- my %search_pack;
- walkoptree(main_root, "lint") if ${main_root()};
-
- # Now do subs in main
- no strict qw(vars refs);
- my $sym;
- local(*glob);
- while (($sym, *glob) = each %{"main::"}) {
- #warn "Trying $sym\n";#debug
- svref_2object(\*glob)->EGV->lintcv unless $sym =~ /::$/;
- }
-
- # Now do subs in non-main packages given by -u options
- map { $search_pack{$_} = 1 } @extra_packages;
- walksymtable(\%{"main::"}, "lintcv", sub {
- my $package = shift;
- $package =~ s/::$//;
- #warn "Considering $package\n";#debug
- return exists $search_pack{$package};
- });
-}
-
-sub compile {
- my @options = @_;
- my ($option, $opt, $arg);
- # Turn on default lint checks
- for $opt (@default_checks) {
- $check{$opt} = 1;
- }
- OPTION:
- while ($option = shift @options) {
- if ($option =~ /^-(.)(.*)/) {
- $opt = $1;
- $arg = $2;
- } else {
- unshift @options, $option;
- last OPTION;
- }
- if ($opt eq "-" && $arg eq "-") {
- shift @options;
- last OPTION;
- } elsif ($opt eq "D") {
- $arg ||= shift @options;
- foreach $arg (split(//, $arg)) {
- if ($arg eq "o") {
- B->debug(1);
- } elsif ($arg eq "O") {
- $debug_op = 1;
- }
- }
- } elsif ($opt eq "u") {
- $arg ||= shift @options;
- push(@extra_packages, $arg);
- }
- }
- foreach $opt (@default_checks, @options) {
- $opt =~ tr/-/_/;
- if ($opt eq "all") {
- %check = %valid_check;
- }
- elsif ($opt eq "none") {
- %check = ();
- }
- else {
- if ($opt =~ s/^no-//) {
- $check{$opt} = 0;
- }
- else {
- $check{$opt} = 1;
- }
- warn "No such check: $opt\n" unless defined $valid_check{$opt};
- }
- }
- # Remaining arguments are things to check
-
- return \&do_lint;
-}
-
-1;
diff --git a/contrib/perl5/ext/B/B/Showlex.pm b/contrib/perl5/ext/B/B/Showlex.pm
deleted file mode 100644
index 842ca3e..0000000
--- a/contrib/perl5/ext/B/B/Showlex.pm
+++ /dev/null
@@ -1,97 +0,0 @@
-package B::Showlex;
-use strict;
-use B qw(svref_2object comppadlist class);
-use B::Terse ();
-
-#
-# Invoke as
-# perl -MO=Showlex,foo bar.pl
-# to see the names of lexical variables used by &foo
-# or as
-# perl -MO=Showlex bar.pl
-# to see the names of file scope lexicals used by bar.pl
-#
-
-sub shownamearray {
- my ($name, $av) = @_;
- my @els = $av->ARRAY;
- my $count = @els;
- my $i;
- print "$name has $count entries\n";
- for ($i = 0; $i < $count; $i++) {
- print "$i: ";
- my $sv = $els[$i];
- if (class($sv) ne "SPECIAL") {
- printf "%s (0x%lx) %s\n", class($sv), $$sv, $sv->PVX;
- } else {
- $sv->terse;
- }
- }
-}
-
-sub showvaluearray {
- my ($name, $av) = @_;
- my @els = $av->ARRAY;
- my $count = @els;
- my $i;
- print "$name has $count entries\n";
- for ($i = 0; $i < $count; $i++) {
- print "$i: ";
- $els[$i]->terse;
- }
-}
-
-sub showlex {
- my ($objname, $namesav, $valsav) = @_;
- shownamearray("Pad of lexical names for $objname", $namesav);
- showvaluearray("Pad of lexical values for $objname", $valsav);
-}
-
-sub showlex_obj {
- my ($objname, $obj) = @_;
- $objname =~ s/^&main::/&/;
- showlex($objname, svref_2object($obj)->PADLIST->ARRAY);
-}
-
-sub showlex_main {
- showlex("comppadlist", comppadlist->ARRAY);
-}
-
-sub compile {
- my @options = @_;
- if (@options) {
- return sub {
- my $objname;
- foreach $objname (@options) {
- $objname = "main::$objname" unless $objname =~ /::/;
- eval "showlex_obj('&$objname', \\&$objname)";
- }
- }
- } else {
- return \&showlex_main;
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Showlex - Show lexical variables used in functions or files
-
-=head1 SYNOPSIS
-
- perl -MO=Showlex[,SUBROUTINE] foo.pl
-
-=head1 DESCRIPTION
-
-When a subroutine name is provided in OPTIONS, prints the lexical
-variables used in that subroutine. Otherwise, prints the file-scope
-lexicals in the file.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Stackobj.pm b/contrib/perl5/ext/B/B/Stackobj.pm
deleted file mode 100644
index 0db3e33..0000000
--- a/contrib/perl5/ext/B/B/Stackobj.pm
+++ /dev/null
@@ -1,346 +0,0 @@
-# Stackobj.pm
-#
-# Copyright (c) 1996 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::Stackobj;
-use Exporter ();
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(set_callback T_UNKNOWN T_DOUBLE T_INT VALID_UNSIGNED
- VALID_INT VALID_DOUBLE VALID_SV REGISTER TEMPORARY);
-%EXPORT_TAGS = (types => [qw(T_UNKNOWN T_DOUBLE T_INT)],
- flags => [qw(VALID_INT VALID_DOUBLE VALID_SV
- VALID_UNSIGNED REGISTER TEMPORARY)]);
-
-use Carp qw(confess);
-use strict;
-use B qw(class SVf_IOK SVf_NOK SVf_IVisUV);
-
-# Types
-sub T_UNKNOWN () { 0 }
-sub T_DOUBLE () { 1 }
-sub T_INT () { 2 }
-sub T_SPECIAL () { 3 }
-
-# Flags
-sub VALID_INT () { 0x01 }
-sub VALID_UNSIGNED () { 0x02 }
-sub VALID_DOUBLE () { 0x04 }
-sub VALID_SV () { 0x08 }
-sub REGISTER () { 0x10 } # no implicit write-back when calling subs
-sub TEMPORARY () { 0x20 } # no implicit write-back needed at all
-sub SAVE_INT () { 0x40 } #if int part needs to be saved at all
-sub SAVE_DOUBLE () { 0x80 } #if double part needs to be saved at all
-
-
-#
-# Callback for runtime code generation
-#
-my $runtime_callback = sub { confess "set_callback not yet called" };
-sub set_callback (&) { $runtime_callback = shift }
-sub runtime { &$runtime_callback(@_) }
-
-#
-# Methods
-#
-
-sub write_back { confess "stack object does not implement write_back" }
-
-sub invalidate { shift->{flags} &= ~(VALID_INT |VALID_UNSIGNED | VALID_DOUBLE) }
-
-sub as_sv {
- my $obj = shift;
- if (!($obj->{flags} & VALID_SV)) {
- $obj->write_back;
- $obj->{flags} |= VALID_SV;
- }
- return $obj->{sv};
-}
-
-sub as_int {
- my $obj = shift;
- if (!($obj->{flags} & VALID_INT)) {
- $obj->load_int;
- $obj->{flags} |= VALID_INT|SAVE_INT;
- }
- return $obj->{iv};
-}
-
-sub as_double {
- my $obj = shift;
- if (!($obj->{flags} & VALID_DOUBLE)) {
- $obj->load_double;
- $obj->{flags} |= VALID_DOUBLE|SAVE_DOUBLE;
- }
- return $obj->{nv};
-}
-
-sub as_numeric {
- my $obj = shift;
- return $obj->{type} == T_INT ? $obj->as_int : $obj->as_double;
-}
-
-sub as_bool {
- my $obj=shift;
- if ($obj->{flags} & VALID_INT ){
- return $obj->{iv};
- }
- if ($obj->{flags} & VALID_DOUBLE ){
- return $obj->{nv};
- }
- return sprintf("(SvTRUE(%s))", $obj->as_sv) ;
-}
-
-#
-# Debugging methods
-#
-sub peek {
- my $obj = shift;
- my $type = $obj->{type};
- my $flags = $obj->{flags};
- my @flags;
- if ($type == T_UNKNOWN) {
- $type = "T_UNKNOWN";
- } elsif ($type == T_INT) {
- $type = "T_INT";
- } elsif ($type == T_DOUBLE) {
- $type = "T_DOUBLE";
- } else {
- $type = "(illegal type $type)";
- }
- push(@flags, "VALID_INT") if $flags & VALID_INT;
- push(@flags, "VALID_DOUBLE") if $flags & VALID_DOUBLE;
- push(@flags, "VALID_SV") if $flags & VALID_SV;
- push(@flags, "REGISTER") if $flags & REGISTER;
- push(@flags, "TEMPORARY") if $flags & TEMPORARY;
- @flags = ("none") unless @flags;
- return sprintf("%s type=$type flags=%s sv=$obj->{sv}",
- class($obj), join("|", @flags));
-}
-
-sub minipeek {
- my $obj = shift;
- my $type = $obj->{type};
- my $flags = $obj->{flags};
- if ($type == T_INT || $flags & VALID_INT) {
- return $obj->{iv};
- } elsif ($type == T_DOUBLE || $flags & VALID_DOUBLE) {
- return $obj->{nv};
- } else {
- return $obj->{sv};
- }
-}
-
-#
-# Caller needs to ensure that set_int, set_double,
-# set_numeric and set_sv are only invoked on legal lvalues.
-#
-sub set_int {
- my ($obj, $expr,$unsigned) = @_;
- runtime("$obj->{iv} = $expr;");
- $obj->{flags} &= ~(VALID_SV | VALID_DOUBLE);
- $obj->{flags} |= VALID_INT|SAVE_INT;
- $obj->{flags} |= VALID_UNSIGNED if $unsigned;
-}
-
-sub set_double {
- my ($obj, $expr) = @_;
- runtime("$obj->{nv} = $expr;");
- $obj->{flags} &= ~(VALID_SV | VALID_INT);
- $obj->{flags} |= VALID_DOUBLE|SAVE_DOUBLE;
-}
-
-sub set_numeric {
- my ($obj, $expr) = @_;
- if ($obj->{type} == T_INT) {
- $obj->set_int($expr);
- } else {
- $obj->set_double($expr);
- }
-}
-
-sub set_sv {
- my ($obj, $expr) = @_;
- runtime("SvSetSV($obj->{sv}, $expr);");
- $obj->invalidate;
- $obj->{flags} |= VALID_SV;
-}
-
-#
-# Stackobj::Padsv
-#
-
-@B::Stackobj::Padsv::ISA = 'B::Stackobj';
-sub B::Stackobj::Padsv::new {
- my ($class, $type, $extra_flags, $ix, $iname, $dname) = @_;
- $extra_flags |= SAVE_INT if $extra_flags & VALID_INT;
- $extra_flags |= SAVE_DOUBLE if $extra_flags & VALID_DOUBLE;
- bless {
- type => $type,
- flags => VALID_SV | $extra_flags,
- sv => "PL_curpad[$ix]",
- iv => "$iname",
- nv => "$dname"
- }, $class;
-}
-
-sub B::Stackobj::Padsv::load_int {
- my $obj = shift;
- if ($obj->{flags} & VALID_DOUBLE) {
- runtime("$obj->{iv} = $obj->{nv};");
- } else {
- runtime("$obj->{iv} = SvIV($obj->{sv});");
- }
- $obj->{flags} |= VALID_INT|SAVE_INT;
-}
-
-sub B::Stackobj::Padsv::load_double {
- my $obj = shift;
- $obj->write_back;
- runtime("$obj->{nv} = SvNV($obj->{sv});");
- $obj->{flags} |= VALID_DOUBLE|SAVE_DOUBLE;
-}
-sub B::Stackobj::Padsv::save_int {
- my $obj = shift;
- return $obj->{flags} & SAVE_INT;
-}
-
-sub B::Stackobj::Padsv::save_double {
- my $obj = shift;
- return $obj->{flags} & SAVE_DOUBLE;
-}
-
-sub B::Stackobj::Padsv::write_back {
- my $obj = shift;
- my $flags = $obj->{flags};
- return if $flags & VALID_SV;
- if ($flags & VALID_INT) {
- if ($flags & VALID_UNSIGNED ){
- runtime("sv_setuv($obj->{sv}, $obj->{iv});");
- }else{
- runtime("sv_setiv($obj->{sv}, $obj->{iv});");
- }
- } elsif ($flags & VALID_DOUBLE) {
- runtime("sv_setnv($obj->{sv}, $obj->{nv});");
- } else {
- confess "write_back failed for lexical @{[$obj->peek]}\n";
- }
- $obj->{flags} |= VALID_SV;
-}
-
-#
-# Stackobj::Const
-#
-
-@B::Stackobj::Const::ISA = 'B::Stackobj';
-sub B::Stackobj::Const::new {
- my ($class, $sv) = @_;
- my $obj = bless {
- flags => 0,
- sv => $sv # holds the SV object until write_back happens
- }, $class;
- if ( ref($sv) eq "B::SPECIAL" ){
- $obj->{type}= T_SPECIAL;
- }else{
- my $svflags = $sv->FLAGS;
- if ($svflags & SVf_IOK) {
- $obj->{flags} = VALID_INT|VALID_DOUBLE;
- $obj->{type} = T_INT;
- if ($svflags & SVf_IVisUV){
- $obj->{flags} |= VALID_UNSIGNED;
- $obj->{nv} = $obj->{iv} = $sv->UVX;
- }else{
- $obj->{nv} = $obj->{iv} = $sv->IV;
- }
- } elsif ($svflags & SVf_NOK) {
- $obj->{flags} = VALID_INT|VALID_DOUBLE;
- $obj->{type} = T_DOUBLE;
- $obj->{iv} = $obj->{nv} = $sv->NV;
- } else {
- $obj->{type} = T_UNKNOWN;
- }
- }
- return $obj;
-}
-
-sub B::Stackobj::Const::write_back {
- my $obj = shift;
- return if $obj->{flags} & VALID_SV;
- # Save the SV object and replace $obj->{sv} by its C source code name
- $obj->{sv} = $obj->{sv}->save;
- $obj->{flags} |= VALID_SV|VALID_INT|VALID_DOUBLE;
-}
-
-sub B::Stackobj::Const::load_int {
- my $obj = shift;
- if (ref($obj->{sv}) eq "B::RV"){
- $obj->{iv} = int($obj->{sv}->RV->PV);
- }else{
- $obj->{iv} = int($obj->{sv}->PV);
- }
- $obj->{flags} |= VALID_INT;
-}
-
-sub B::Stackobj::Const::load_double {
- my $obj = shift;
- if (ref($obj->{sv}) eq "B::RV"){
- $obj->{nv} = $obj->{sv}->RV->PV + 0.0;
- }else{
- $obj->{nv} = $obj->{sv}->PV + 0.0;
- }
- $obj->{flags} |= VALID_DOUBLE;
-}
-
-sub B::Stackobj::Const::invalidate {}
-
-#
-# Stackobj::Bool
-#
-
-@B::Stackobj::Bool::ISA = 'B::Stackobj';
-sub B::Stackobj::Bool::new {
- my ($class, $preg) = @_;
- my $obj = bless {
- type => T_INT,
- flags => VALID_INT|VALID_DOUBLE,
- iv => $$preg,
- nv => $$preg,
- preg => $preg # this holds our ref to the pseudo-reg
- }, $class;
- return $obj;
-}
-
-sub B::Stackobj::Bool::write_back {
- my $obj = shift;
- return if $obj->{flags} & VALID_SV;
- $obj->{sv} = "($obj->{iv} ? &PL_sv_yes : &PL_sv_no)";
- $obj->{flags} |= VALID_SV;
-}
-
-# XXX Might want to handle as_double/set_double/load_double?
-
-sub B::Stackobj::Bool::invalidate {}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Stackobj - Helper module for CC backend
-
-=head1 SYNOPSIS
-
- use B::Stackobj;
-
-=head1 DESCRIPTION
-
-See F<ext/B/README>.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Stash.pm b/contrib/perl5/ext/B/B/Stash.pm
deleted file mode 100644
index f3a8247..0000000
--- a/contrib/perl5/ext/B/B/Stash.pm
+++ /dev/null
@@ -1,50 +0,0 @@
-# Stash.pm -- show what stashes are loaded
-# vishalb@hotmail.com
-package B::Stash;
-
-=pod
-
-=head1 NAME
-
-B::Stash - show what stashes are loaded
-
-=cut
-
-BEGIN { %Seen = %INC }
-
-CHECK {
- my @arr=scan($main::{"main::"});
- @arr=map{s/\:\:$//;$_ eq "<none>"?():$_;} @arr;
- print "-umain,-u", join (",-u",@arr) ,"\n";
-}
-sub scan{
- my $start=shift;
- my $prefix=shift;
- $prefix = '' unless defined $prefix;
- my @return;
- foreach my $key ( keys %{$start}){
-# print $prefix,$key,"\n";
- if ($key =~ /::$/){
- unless ($start eq ${$start}{$key} or $key eq "B::" ){
- push @return, $key unless omit($prefix.$key);
- foreach my $subscan ( scan(${$start}{$key},$prefix.$key)){
- push @return, "$key".$subscan;
- }
- }
- }
- }
- return @return;
-}
-sub omit{
- my $module = shift;
- my %omit=("DynaLoader::" => 1 , "XSLoader::" => 1, "CORE::" => 1 ,
- "CORE::GLOBAL::" => 1, "UNIVERSAL::" => 1 );
- return 1 if $omit{$module};
- if ($module eq "IO::" or $module eq "IO::Handle::"){
- $module =~ s/::/\//g;
- return 1 unless $INC{$module};
- }
-
- return 0;
-}
-1;
diff --git a/contrib/perl5/ext/B/B/Terse.pm b/contrib/perl5/ext/B/B/Terse.pm
deleted file mode 100644
index 52f0549..0000000
--- a/contrib/perl5/ext/B/B/Terse.pm
+++ /dev/null
@@ -1,153 +0,0 @@
-package B::Terse;
-use strict;
-use B qw(peekop class walkoptree walkoptree_exec walkoptree_slow
- main_start main_root cstring svref_2object SVf_IVisUV);
-use B::Asmdata qw(@specialsv_name);
-
-sub terse {
- my ($order, $cvref) = @_;
- my $cv = svref_2object($cvref);
- if ($order eq "exec") {
- walkoptree_exec($cv->START, "terse");
- } else {
- walkoptree_slow($cv->ROOT, "terse");
- }
-}
-
-sub compile {
- my $order = @_ ? shift : "";
- my @options = @_;
- B::clearsym();
- if (@options) {
- return sub {
- my $objname;
- foreach $objname (@options) {
- $objname = "main::$objname" unless $objname =~ /::/;
- eval "terse(\$order, \\&$objname)";
- die "terse($order, \\&$objname) failed: $@" if $@;
- }
- }
- } else {
- if ($order eq "exec") {
- return sub { walkoptree_exec(main_start, "terse") }
- } else {
- return sub { walkoptree_slow(main_root, "terse") }
- }
- }
-}
-
-sub indent {
- my $level = @_ ? shift : 0;
- return " " x $level;
-}
-
-sub B::OP::terse {
- my ($op, $level) = @_;
- my $targ = $op->targ;
- $targ = ($targ > 0) ? " [$targ]" : "";
- print indent($level), peekop($op), $targ, "\n";
-}
-
-sub B::SVOP::terse {
- my ($op, $level) = @_;
- print indent($level), peekop($op), " ";
- $op->sv->terse(0);
-}
-
-sub B::PADOP::terse {
- my ($op, $level) = @_;
- print indent($level), peekop($op), " ", $op->padix, "\n";
-}
-
-sub B::PMOP::terse {
- my ($op, $level) = @_;
- my $precomp = $op->precomp;
- print indent($level), peekop($op),
- defined($precomp) ? " /$precomp/\n" : " (regexp not compiled)\n";
-
-}
-
-sub B::PVOP::terse {
- my ($op, $level) = @_;
- print indent($level), peekop($op), " ", cstring($op->pv), "\n";
-}
-
-sub B::COP::terse {
- my ($op, $level) = @_;
- my $label = $op->label;
- if ($label) {
- $label = " label ".cstring($label);
- }
- print indent($level), peekop($op), $label || "", "\n";
-}
-
-sub B::PV::terse {
- my ($sv, $level) = @_;
- print indent($level);
- printf "%s (0x%lx) %s\n", class($sv), $$sv, cstring($sv->PV);
-}
-
-sub B::AV::terse {
- my ($sv, $level) = @_;
- print indent($level);
- printf "%s (0x%lx) FILL %d\n", class($sv), $$sv, $sv->FILL;
-}
-
-sub B::GV::terse {
- my ($gv, $level) = @_;
- my $stash = $gv->STASH->NAME;
- if ($stash eq "main") {
- $stash = "";
- } else {
- $stash = $stash . "::";
- }
- print indent($level);
- printf "%s (0x%lx) *%s%s\n", class($gv), $$gv, $stash, $gv->SAFENAME;
-}
-
-sub B::IV::terse {
- my ($sv, $level) = @_;
- print indent($level);
- my $v = $sv->FLAGS & SVf_IVisUV ? "%u" : "%d";
- printf "%s (0x%lx) $v\n", class($sv), $$sv, $sv->int_value;
-}
-
-sub B::NV::terse {
- my ($sv, $level) = @_;
- print indent($level);
- printf "%s (0x%lx) %s\n", class($sv), $$sv, $sv->NV;
-}
-
-sub B::NULL::terse {
- my ($sv, $level) = @_;
- print indent($level);
- printf "%s (0x%lx)\n", class($sv), $$sv;
-}
-
-sub B::SPECIAL::terse {
- my ($sv, $level) = @_;
- print indent($level);
- printf "%s #%d %s\n", class($sv), $$sv, $specialsv_name[$$sv];
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-B::Terse - Walk Perl syntax tree, printing terse info about ops
-
-=head1 SYNOPSIS
-
- perl -MO=Terse[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-See F<ext/B/README>.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/B/Xref.pm b/contrib/perl5/ext/B/B/Xref.pm
deleted file mode 100644
index b4078b8..0000000
--- a/contrib/perl5/ext/B/B/Xref.pm
+++ /dev/null
@@ -1,420 +0,0 @@
-package B::Xref;
-
-=head1 NAME
-
-B::Xref - Generates cross reference reports for Perl programs
-
-=head1 SYNOPSIS
-
-perl -MO=Xref[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-The B::Xref module is used to generate a cross reference listing of all
-definitions and uses of variables, subroutines and formats in a Perl program.
-It is implemented as a backend for the Perl compiler.
-
-The report generated is in the following format:
-
- File filename1
- Subroutine subname1
- Package package1
- object1 C<line numbers>
- object2 C<line numbers>
- ...
- Package package2
- ...
-
-Each B<File> section reports on a single file. Each B<Subroutine> section
-reports on a single subroutine apart from the special cases
-"(definitions)" and "(main)". These report, respectively, on subroutine
-definitions found by the initial symbol table walk and on the main part of
-the program or module external to all subroutines.
-
-The report is then grouped by the B<Package> of each variable,
-subroutine or format with the special case "(lexicals)" meaning
-lexical variables. Each B<object> name (implicitly qualified by its
-containing B<Package>) includes its type character(s) at the beginning
-where possible. Lexical variables are easier to track and even
-included dereferencing information where possible.
-
-The C<line numbers> are a comma separated list of line numbers (some
-preceded by code letters) where that object is used in some way.
-Simple uses aren't preceded by a code letter. Introductions (such as
-where a lexical is first defined with C<my>) are indicated with the
-letter "i". Subroutine and method calls are indicated by the character
-"&". Subroutine definitions are indicated by "s" and format
-definitions by "f".
-
-=head1 OPTIONS
-
-Option words are separated by commas (not whitespace) and follow the
-usual conventions of compiler backend options.
-
-=over 8
-
-=item C<-oFILENAME>
-
-Directs output to C<FILENAME> instead of standard output.
-
-=item C<-r>
-
-Raw output. Instead of producing a human-readable report, outputs a line
-in machine-readable form for each definition/use of a variable/sub/format.
-
-=item C<-D[tO]>
-
-(Internal) debug options, probably only useful if C<-r> included.
-The C<t> option prints the object on the top of the stack as it's
-being tracked. The C<O> option prints each operator as it's being
-processed in the execution order of the program.
-
-=back
-
-=head1 BUGS
-
-Non-lexical variables are quite difficult to track through a program.
-Sometimes the type of a non-lexical variable's use is impossible to
-determine. Introductions of non-lexical non-scalars don't seem to be
-reported properly.
-
-=head1 AUTHOR
-
-Malcolm Beattie, mbeattie@sable.ox.ac.uk.
-
-=cut
-
-use strict;
-use Config;
-use B qw(peekop class comppadlist main_start svref_2object walksymtable
- OPpLVAL_INTRO SVf_POK
- );
-
-sub UNKNOWN { ["?", "?", "?"] }
-
-my @pad; # lexicals in current pad
- # as ["(lexical)", type, name]
-my %done; # keyed by $$op: set when each $op is done
-my $top = UNKNOWN; # shadows top element of stack as
- # [pack, type, name] (pack can be "(lexical)")
-my $file; # shadows current filename
-my $line; # shadows current line number
-my $subname; # shadows current sub name
-my %table; # Multi-level hash to record all uses etc.
-my @todo = (); # List of CVs that need processing
-
-my %code = (intro => "i", used => "",
- subdef => "s", subused => "&",
- formdef => "f", meth => "->");
-
-
-# Options
-my ($debug_op, $debug_top, $nodefs, $raw);
-
-sub process {
- my ($var, $event) = @_;
- my ($pack, $type, $name) = @$var;
- if ($type eq "*") {
- if ($event eq "used") {
- return;
- } elsif ($event eq "subused") {
- $type = "&";
- }
- }
- $type =~ s/(.)\*$/$1/g;
- if ($raw) {
- printf "%-16s %-12s %5d %-12s %4s %-16s %s\n",
- $file, $subname, $line, $pack, $type, $name, $event;
- } else {
- # Wheee
- push(@{$table{$file}->{$subname}->{$pack}->{$type.$name}->{$event}},
- $line);
- }
-}
-
-sub load_pad {
- my $padlist = shift;
- my ($namelistav, $vallistav, @namelist, $ix);
- @pad = ();
- return if class($padlist) eq "SPECIAL";
- ($namelistav,$vallistav) = $padlist->ARRAY;
- @namelist = $namelistav->ARRAY;
- for ($ix = 1; $ix < @namelist; $ix++) {
- my $namesv = $namelist[$ix];
- next if class($namesv) eq "SPECIAL";
- my ($type, $name) = $namesv->PV =~ /^(.)([^\0]*)(\0.*)?$/;
- $pad[$ix] = ["(lexical)", $type, $name];
- }
- if ($Config{useithreads}) {
- my (@vallist);
- @vallist = $vallistav->ARRAY;
- for ($ix = 1; $ix < @vallist; $ix++) {
- my $valsv = $vallist[$ix];
- next unless class($valsv) eq "GV";
- # these pad GVs don't have corresponding names, so same @pad
- # array can be used without collisions
- $pad[$ix] = [$valsv->STASH->NAME, "*", $valsv->NAME];
- }
- }
-}
-
-sub xref {
- my $start = shift;
- my $op;
- for ($op = $start; $$op; $op = $op->next) {
- last if $done{$$op}++;
- warn sprintf("top = [%s, %s, %s]\n", @$top) if $debug_top;
- warn peekop($op), "\n" if $debug_op;
- my $opname = $op->name;
- if ($opname =~ /^(or|and|mapwhile|grepwhile|range|cond_expr)$/) {
- xref($op->other);
- } elsif ($opname eq "match" || $opname eq "subst") {
- xref($op->pmreplstart);
- } elsif ($opname eq "substcont") {
- xref($op->other->pmreplstart);
- $op = $op->other;
- redo;
- } elsif ($opname eq "enterloop") {
- xref($op->redoop);
- xref($op->nextop);
- xref($op->lastop);
- } elsif ($opname eq "subst") {
- xref($op->pmreplstart);
- } else {
- no strict 'refs';
- my $ppname = "pp_$opname";
- &$ppname($op) if defined(&$ppname);
- }
- }
-}
-
-sub xref_cv {
- my $cv = shift;
- my $pack = $cv->GV->STASH->NAME;
- $subname = ($pack eq "main" ? "" : "$pack\::") . $cv->GV->NAME;
- load_pad($cv->PADLIST);
- xref($cv->START);
- $subname = "(main)";
-}
-
-sub xref_object {
- my $cvref = shift;
- xref_cv(svref_2object($cvref));
-}
-
-sub xref_main {
- $subname = "(main)";
- load_pad(comppadlist);
- xref(main_start);
- while (@todo) {
- xref_cv(shift @todo);
- }
-}
-
-sub pp_nextstate {
- my $op = shift;
- $file = $op->file;
- $line = $op->line;
- $top = UNKNOWN;
-}
-
-sub pp_padsv {
- my $op = shift;
- $top = $pad[$op->targ];
- process($top, $op->private & OPpLVAL_INTRO ? "intro" : "used");
-}
-
-sub pp_padav { pp_padsv(@_) }
-sub pp_padhv { pp_padsv(@_) }
-
-sub deref {
- my ($var, $as) = @_;
- $var->[1] = $as . $var->[1];
- process($var, "used");
-}
-
-sub pp_rv2cv { deref($top, "&"); }
-sub pp_rv2hv { deref($top, "%"); }
-sub pp_rv2sv { deref($top, "\$"); }
-sub pp_rv2av { deref($top, "\@"); }
-sub pp_rv2gv { deref($top, "*"); }
-
-sub pp_gvsv {
- my $op = shift;
- my $gv;
- if ($Config{useithreads}) {
- $top = $pad[$op->padix];
- $top = UNKNOWN unless $top;
- $top->[1] = '$';
- }
- else {
- $gv = $op->gv;
- $top = [$gv->STASH->NAME, '$', $gv->NAME];
- }
- process($top, $op->private & OPpLVAL_INTRO ? "intro" : "used");
-}
-
-sub pp_gv {
- my $op = shift;
- my $gv;
- if ($Config{useithreads}) {
- $top = $pad[$op->padix];
- $top = UNKNOWN unless $top;
- $top->[1] = '*';
- }
- else {
- $gv = $op->gv;
- $top = [$gv->STASH->NAME, "*", $gv->NAME];
- }
- process($top, $op->private & OPpLVAL_INTRO ? "intro" : "used");
-}
-
-sub pp_const {
- my $op = shift;
- my $sv = $op->sv;
- # constant could be in the pad (under useithreads)
- if ($$sv) {
- $top = ["?", "",
- (class($sv) ne "SPECIAL" && $sv->FLAGS & SVf_POK) ? $sv->PV : "?"];
- }
- else {
- $top = $pad[$op->targ];
- }
-}
-
-sub pp_method {
- my $op = shift;
- $top = ["(method)", "->".$top->[1], $top->[2]];
-}
-
-sub pp_entersub {
- my $op = shift;
- if ($top->[1] eq "m") {
- process($top, "meth");
- } else {
- process($top, "subused");
- }
- $top = UNKNOWN;
-}
-
-#
-# Stuff for cross referencing definitions of variables and subs
-#
-
-sub B::GV::xref {
- my $gv = shift;
- my $cv = $gv->CV;
- if ($$cv) {
- #return if $done{$$cv}++;
- $file = $gv->FILE;
- $line = $gv->LINE;
- process([$gv->STASH->NAME, "&", $gv->NAME], "subdef");
- push(@todo, $cv);
- }
- my $form = $gv->FORM;
- if ($$form) {
- return if $done{$$form}++;
- $file = $gv->FILE;
- $line = $gv->LINE;
- process([$gv->STASH->NAME, "", $gv->NAME], "formdef");
- }
-}
-
-sub xref_definitions {
- my ($pack, %exclude);
- return if $nodefs;
- $subname = "(definitions)";
- foreach $pack (qw(B O AutoLoader DynaLoader XSLoader Config DB VMS
- strict vars FileHandle Exporter Carp)) {
- $exclude{$pack."::"} = 1;
- }
- no strict qw(vars refs);
- walksymtable(\%{"main::"}, "xref", sub { !defined($exclude{$_[0]}) });
-}
-
-sub output {
- return if $raw;
- my ($file, $subname, $pack, $name, $ev, $perfile, $persubname,
- $perpack, $pername, $perev);
- foreach $file (sort(keys(%table))) {
- $perfile = $table{$file};
- print "File $file\n";
- foreach $subname (sort(keys(%$perfile))) {
- $persubname = $perfile->{$subname};
- print " Subroutine $subname\n";
- foreach $pack (sort(keys(%$persubname))) {
- $perpack = $persubname->{$pack};
- print " Package $pack\n";
- foreach $name (sort(keys(%$perpack))) {
- $pername = $perpack->{$name};
- my @lines;
- foreach $ev (qw(intro formdef subdef meth subused used)) {
- $perev = $pername->{$ev};
- if (defined($perev) && @$perev) {
- my $code = $code{$ev};
- push(@lines, map("$code$_", @$perev));
- }
- }
- printf " %-16s %s\n", $name, join(", ", @lines);
- }
- }
- }
- }
-}
-
-sub compile {
- my @options = @_;
- my ($option, $opt, $arg);
- OPTION:
- while ($option = shift @options) {
- if ($option =~ /^-(.)(.*)/) {
- $opt = $1;
- $arg = $2;
- } else {
- unshift @options, $option;
- last OPTION;
- }
- if ($opt eq "-" && $arg eq "-") {
- shift @options;
- last OPTION;
- } elsif ($opt eq "o") {
- $arg ||= shift @options;
- open(STDOUT, ">$arg") or return "$arg: $!\n";
- } elsif ($opt eq "d") {
- $nodefs = 1;
- } elsif ($opt eq "r") {
- $raw = 1;
- } elsif ($opt eq "D") {
- $arg ||= shift @options;
- foreach $arg (split(//, $arg)) {
- if ($arg eq "o") {
- B->debug(1);
- } elsif ($arg eq "O") {
- $debug_op = 1;
- } elsif ($arg eq "t") {
- $debug_top = 1;
- }
- }
- }
- }
- if (@options) {
- return sub {
- my $objname;
- xref_definitions();
- foreach $objname (@options) {
- $objname = "main::$objname" unless $objname =~ /::/;
- eval "xref_object(\\&$objname)";
- die "xref_object(\\&$objname) failed: $@" if $@;
- }
- output();
- }
- } else {
- return sub {
- xref_definitions();
- xref_main();
- output();
- }
- }
-}
-
-1;
diff --git a/contrib/perl5/ext/B/B/assemble b/contrib/perl5/ext/B/B/assemble
deleted file mode 100755
index 43cc5bc..0000000
--- a/contrib/perl5/ext/B/B/assemble
+++ /dev/null
@@ -1,30 +0,0 @@
-use B::Assembler qw(assemble_fh);
-use FileHandle;
-
-my ($filename, $fh, $out);
-
-if ($ARGV[0] eq "-d") {
- B::Assembler::debug(1);
- shift;
-}
-
-$out = \*STDOUT;
-
-if (@ARGV == 0) {
- $fh = \*STDIN;
- $filename = "-";
-} elsif (@ARGV == 1) {
- $filename = $ARGV[0];
- $fh = new FileHandle "<$filename";
-} elsif (@ARGV == 2) {
- $filename = $ARGV[0];
- $fh = new FileHandle "<$filename";
- $out = new FileHandle ">$ARGV[1]";
-} else {
- die "Usage: assemble [filename] [outfilename]\n";
-}
-
-binmode $out;
-$SIG{__WARN__} = sub { warn "$filename:@_" };
-$SIG{__DIE__} = sub { die "$filename: @_" };
-assemble_fh($fh, sub { print $out @_ });
diff --git a/contrib/perl5/ext/B/B/cc_harness b/contrib/perl5/ext/B/B/cc_harness
deleted file mode 100644
index 79f8727..0000000
--- a/contrib/perl5/ext/B/B/cc_harness
+++ /dev/null
@@ -1,12 +0,0 @@
-use Config;
-
-$libdir = $ENV{PERL_SRC} || "$Config{installarchlib}/CORE";
-
-if (!grep(/^-[cS]$/, @ARGV)) {
- $linkargs = sprintf("%s $libdir/$Config{libperl} %s",
- @Config{qw(ldflags libs)});
-}
-
-$cccmd = "$Config{cc} $Config{ccflags} -I$libdir @ARGV $linkargs";
-print "$cccmd\n";
-exec $cccmd;
diff --git a/contrib/perl5/ext/B/B/disassemble b/contrib/perl5/ext/B/B/disassemble
deleted file mode 100755
index 6530b80..0000000
--- a/contrib/perl5/ext/B/B/disassemble
+++ /dev/null
@@ -1,22 +0,0 @@
-use B::Disassembler qw(disassemble_fh);
-use FileHandle;
-
-my $fh;
-if (@ARGV == 0) {
- $fh = \*STDIN;
-} elsif (@ARGV == 1) {
- $fh = new FileHandle "<$ARGV[0]";
-} else {
- die "Usage: disassemble [filename]\n";
-}
-
-sub print_insn {
- my ($insn, $arg) = @_;
- if (defined($arg)) {
- printf "%s %s\n", $insn, $arg;
- } else {
- print $insn, "\n";
- }
-}
-
-disassemble_fh($fh, \&print_insn);
diff --git a/contrib/perl5/ext/B/B/makeliblinks b/contrib/perl5/ext/B/B/makeliblinks
deleted file mode 100644
index 8256078..0000000
--- a/contrib/perl5/ext/B/B/makeliblinks
+++ /dev/null
@@ -1,54 +0,0 @@
-use File::Find;
-use Config;
-
-if (@ARGV != 2) {
- warn <<"EOT";
-Usage: makeliblinks libautodir targetdir
-where libautodir is the architecture-dependent auto directory
-(e.g. $Config::Config{archlib}/auto).
-EOT
- exit 2;
-}
-
-my ($libautodir, $targetdir) = @ARGV;
-
-# Calculate relative path prefix from $targetdir to $libautodir
-sub relprefix {
- my ($to, $from) = @_;
- my $up;
- for ($up = 0; substr($to, 0, length($from)) ne $from; $up++) {
- $from =~ s(
- [^/]+ (?# a group of non-slashes)
- /* (?# maybe with some trailing slashes)
- $ (?# at the end of the path)
- )()x;
- }
- return (("../" x $up) . substr($to, length($from)));
-}
-
-my $relprefix = relprefix($libautodir, $targetdir);
-
-my ($dlext, $lib_ext) = @Config::Config{qw(dlext lib_ext)};
-
-sub link_if_library {
- if (/\.($dlext|$lib_ext)$/o) {
- my $ext = $1;
- my $name = $File::Find::name;
- if (substr($name, 0, length($libautodir) + 1) ne "$libautodir/") {
- die "directory of $name doesn't match $libautodir\n";
- }
- substr($name, 0, length($libautodir) + 1) = '';
- my @parts = split(m(/), $name);
- if ($parts[-1] ne "$parts[-2].$ext") {
- die "module name $_ doesn't match its directory $libautodir\n";
- }
- pop @parts;
- my $libpath = "$targetdir/lib" . join("__", @parts) . ".$ext";
- print "$libpath -> $relprefix/$name\n";
- symlink("$relprefix/$name", $libpath)
- or warn "above link failed with error: $!\n";
- }
-}
-
-find(\&link_if_library, $libautodir);
-exit 0;
diff --git a/contrib/perl5/ext/B/Makefile.PL b/contrib/perl5/ext/B/Makefile.PL
deleted file mode 100644
index dcf6a1d..0000000
--- a/contrib/perl5/ext/B/Makefile.PL
+++ /dev/null
@@ -1,48 +0,0 @@
-use ExtUtils::MakeMaker;
-use Config;
-use File::Spec;
-
-my $e = $Config{'exe_ext'};
-my $o = $Config{'obj_ext'};
-my $exeout_flag = '-o ';
-if ($^O eq 'MSWin32') {
- if ($Config{'cc'} =~ /^cl/i) {
- $exeout_flag = '-Fe';
- }
- elsif ($Config{'cc'} =~ /^bcc/i) {
- $exeout_flag = '-e';
- }
-}
-
-WriteMakefile(
- NAME => "B",
- VERSION => "a5",
- PL_FILES => { 'defsubs_h.PL' => 'defsubs.h' },
- MAN3PODS => {},
- clean => {
- FILES => "perl$e *$o B.c defsubs.h *~"
- }
-);
-
-package MY;
-
-sub post_constants {
- "\nLIBS = $Config::Config{libs}\n"
-}
-
-sub upupfile {
- File::Spec->catfile(File::Spec->updir,
- File::Spec->updir, $_[0]);
-}
-
-sub MY::postamble {
- my $op_h = upupfile('op.h');
- my $cop_h = upupfile('cop.h');
- my $noecho = shift->{NOECHO};
-"
-B\$(OBJ_EXT) : defsubs.h
-
-defsubs.h :: $op_h $cop_h
- $noecho \$(NOOP)
-"
-}
diff --git a/contrib/perl5/ext/B/NOTES b/contrib/perl5/ext/B/NOTES
deleted file mode 100644
index 89d03ba..0000000
--- a/contrib/perl5/ext/B/NOTES
+++ /dev/null
@@ -1,168 +0,0 @@
-C backend invocation
- If there are any non-option arguments, they are taken to be
- names of objects to be saved (probably doesn't work properly yet).
- Without extra arguments, it saves the main program.
- -ofilename Output to filename instead of STDOUT
- -v Verbose (currently gives a few compilation statistics)
- -- Force end of options
- -uPackname Force apparently unused subs from package Packname to
- be compiled. This allows programs to use eval "foo()"
- even when sub foo is never seen to be used at compile
- time. The down side is that any subs which really are
- never used also have code generated. This option is
- necessary, for example, if you have a signal handler
- foo which you initialise with $SIG{BAR} = "foo".
- A better fix, though, is just to change it to
- $SIG{BAR} = \&foo. You can have multiple -u options.
- -D Debug options (concat or separate flags like perl -D)
- o OPs, prints each OP as it's processed
- c COPs, prints COPs as processed (incl. file & line num)
- A prints AV information on saving
- C prints CV information on saving
- M prints MAGIC information on saving
- -f Force optimisations on or off one at a time.
- cog Copy-on-grow: PVs declared and initialised statically
- no-cog No copy-on-grow
- -On Optimisation level (n = 0, 1, 2, ...). -O means -O1.
- Currently, -O1 and higher set -fcog.
-
-Examples
- perl -MO=C foo.pl > foo.c
- perl cc_harness -o foo foo.c
-
- perl -MO=C,-v,-DcA bar.pl > /dev/null
-
-CC backend invocation
- If there are any non-option arguments, they are taken to be names of
- subs to be saved. Without extra arguments, it saves the main program.
- -ofilename Output to filename instead of STDOUT
- -- Force end of options
- -uPackname Force apparently unused subs from package Packname to
- be compiled. This allows programs to use eval "foo()"
- even when sub foo is never seen to be used at compile
- time. The down side is that any subs which really are
- never used also have code generated. This option is
- necessary, for example, if you have a signal handler
- foo which you initialise with $SIG{BAR} = "foo".
- A better fix, though, is just to change it to
- $SIG{BAR} = \&foo. You can have multiple -u options.
- -mModulename Instead of generating source for a runnable executable,
- generate source for an XSUB module. The
- boot_Modulename function (which DynaLoader can look
- for) does the appropriate initialisation and runs the
- main part of the Perl source that is being compiled.
- -pn Generate code for perl patchlevel n (e.g. 3 or 4).
- The default is to generate C code which will link
- with the currently executing version of perl.
- running the perl compiler.
- -D Debug options (concat or separate flags like perl -D)
- r Writes debugging output to STDERR just as it's about
- to write to the program's runtime (otherwise writes
- debugging info as comments in its C output).
- O Outputs each OP as it's compiled
- s Outputs the contents of the shadow stack at each OP
- p Outputs the contents of the shadow pad of lexicals as
- it's loaded for each sub or the main program.
- q Outputs the name of each fake PP function in the queue
- as it's about to processes.
- l Output the filename and line number of each original
- line of Perl code as it's processed (pp_nextstate).
- t Outputs timing information of compilation stages
- -f Force optimisations on or off one at a time.
- [
- cog Copy-on-grow: PVs declared and initialised statically
- no-cog No copy-on-grow
- These two not in CC yet.
- ]
- freetmps-each-bblock Delays FREETMPS from the end of each
- statement to the end of the each basic
- block.
- freetmps-each-loop Delays FREETMPS from the end of each
- statement to the end of the group of
- basic blocks forming a loop. At most
- one of the freetmps-each-* options can
- be used.
- omit-taint Omits generating code for handling
- perl's tainting mechanism.
- -On Optimisation level (n = 0, 1, 2, ...). -O means -O1.
- Currently, -O1 sets -ffreetmps-each-bblock and -O2
- sets -ffreetmps-each-loop.
-
-Example
- perl -MO=CC,-O2,-ofoo.c foo.pl
- perl cc_harness -o foo foo.c
-
- perl -MO=CC,-mFoo,-oFoo.c Foo.pm
- perl cc_harness -shared -c -o Foo.so Foo.c
-
-
-Bytecode backend invocation
-
- If there are any non-option arguments, they are taken to be
- names of objects to be saved (probably doesn't work properly yet).
- Without extra arguments, it saves the main program.
- -ofilename Output to filename instead of STDOUT.
- -- Force end of options.
- -f Force optimisations on or off one at a time.
- Each can be preceded by no- to turn the option off.
- compress-nullops
- Only fills in the necessary fields of ops which have
- been optimised away by perl's internal compiler.
- omit-sequence-numbers
- Leaves out code to fill in the op_seq field of all ops
- which is only used by perl's internal compiler.
- bypass-nullops
- If op->op_next ever points to a NULLOP, replaces the
- op_next field with the first non-NULLOP in the path
- of execution.
- strip-syntax-tree
- Leaves out code to fill in the pointers which link the
- internal syntax tree together. They're not needed at
- run-time but leaving them out will make it impossible
- to recompile or disassemble the resulting program.
- It will also stop "goto label" statements from working.
- -On Optimisation level (n = 0, 1, 2, ...). -O means -O1.
- -O1 sets -fcompress-nullops -fomit-sequence numbers.
- -O6 adds -fstrip-syntax-tree.
- -D Debug options (concat or separate flags like perl -D)
- o OPs, prints each OP as it's processed.
- b print debugging information about bytecompiler progress
- a tells the assembler to include source assembler lines
- in its output as bytecode comments.
- C prints each CV taken from the final symbol tree walk.
- -S Output assembler source rather than piping it
- through the assembler and outputting bytecode.
- -m Compile as a module rather than a standalone program.
- Currently this just means that the bytecodes for
- initialising main_start, main_root and curpad are
- omitted.
-
-Example
- perl -MO=Bytecode,-O6,-o,foo.plc foo.pl
-
- perl -MO=Bytecode,-S foo.pl > foo.S
- assemble foo.S > foo.plc
- byteperl foo.plc
-
- perl -MO=Bytecode,-m,-oFoo.pmc Foo.pm
-
-Backends for debugging
- perl -MO=Terse,exec foo.pl
- perl -MO=Debug bar.pl
-
-O module
- Used with "perl -MO=Backend,foo,bar prog.pl" to invoke the backend
- B::Backend with options foo and bar. O invokes the sub
- B::Backend::compile() with arguments foo and bar at BEGIN time.
- That compile() sub must do any inital argument processing replied.
- If unsuccessful, it should return a string which O arranges to be
- printed as an error message followed by a clean error exit. In the
- normal case where any option processing in compile() is successful,
- it should return a sub ref (usually a closure) to perform the
- actual compilation. When O regains control, it ensures that the
- "-c" option is forced (so that the program being compiled doesn't
- end up running) and registers a CHECK block to call back the sub ref
- returned from the backend's compile(). Perl then continues by
- parsing prog.pl (just as it would with "perl -c prog.pl") and after
- doing so, assuming there are no parse-time errors, the CHECK block
- of O gets called and the actual backend compilation happens. Phew.
diff --git a/contrib/perl5/ext/B/O.pm b/contrib/perl5/ext/B/O.pm
deleted file mode 100644
index 2ef91ed..0000000
--- a/contrib/perl5/ext/B/O.pm
+++ /dev/null
@@ -1,86 +0,0 @@
-package O;
-use B qw(minus_c save_BEGINs);
-use Carp;
-
-sub import {
- my ($class, $backend, @options) = @_;
- eval "use B::$backend ()";
- if ($@) {
- croak "use of backend $backend failed: $@";
- }
- my $compilesub = &{"B::${backend}::compile"}(@options);
- if (ref($compilesub) eq "CODE") {
- minus_c;
- save_BEGINs;
- eval 'CHECK { &$compilesub() }';
- } else {
- die $compilesub;
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-O - Generic interface to Perl Compiler backends
-
-=head1 SYNOPSIS
-
- perl -MO=Backend[,OPTIONS] foo.pl
-
-=head1 DESCRIPTION
-
-This is the module that is used as a frontend to the Perl Compiler.
-
-=head1 CONVENTIONS
-
-Most compiler backends use the following conventions: OPTIONS
-consists of a comma-separated list of words (no white-space).
-The C<-v> option usually puts the backend into verbose mode.
-The C<-ofile> option generates output to B<file> instead of
-stdout. The C<-D> option followed by various letters turns on
-various internal debugging flags. See the documentation for the
-desired backend (named C<B::Backend> for the example above) to
-find out about that backend.
-
-=head1 IMPLEMENTATION
-
-This section is only necessary for those who want to write a
-compiler backend module that can be used via this module.
-
-The command-line mentioned in the SYNOPSIS section corresponds to
-the Perl code
-
- use O ("Backend", OPTIONS);
-
-The C<import> function which that calls loads in the appropriate
-C<B::Backend> module and calls the C<compile> function in that
-package, passing it OPTIONS. That function is expected to return
-a sub reference which we'll call CALLBACK. Next, the "compile-only"
-flag is switched on (equivalent to the command-line option C<-c>)
-and a CHECK block is registered which calls CALLBACK. Thus the main
-Perl program mentioned on the command-line is read in, parsed and
-compiled into internal syntax tree form. Since the C<-c> flag is
-set, the program does not start running (excepting BEGIN blocks of
-course) but the CALLBACK function registered by the compiler
-backend is called.
-
-In summary, a compiler backend module should be called "B::Foo"
-for some foo and live in the appropriate directory for that name.
-It should define a function called C<compile>. When the user types
-
- perl -MO=Foo,OPTIONS foo.pl
-
-that function is called and is passed those OPTIONS (split on
-commas). It should return a sub ref to the main compilation function.
-After the user's program is loaded and parsed, that returned sub ref
-is invoked which can then go ahead and do the compilation, usually by
-making use of the C<B> module's functionality.
-
-=head1 AUTHOR
-
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
-
-=cut
diff --git a/contrib/perl5/ext/B/README b/contrib/perl5/ext/B/README
deleted file mode 100644
index fa3f085..0000000
--- a/contrib/perl5/ext/B/README
+++ /dev/null
@@ -1,325 +0,0 @@
- Perl Compiler Kit, Version alpha4
-
- Copyright (c) 1996, 1997, Malcolm Beattie
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of either:
-
- a) the GNU General Public License as published by the Free
- Software Foundation; either version 1, or (at your option) any
- later version, or
-
- b) the "Artistic License" which comes with this kit.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
- the GNU General Public License or the Artistic License for more details.
-
- You should have received a copy of the Artistic License with this kit,
- in the file named "Artistic". If not, you can get one from the Perl
- distribution. You should also have received a copy of the GNU General
- Public License, in the file named "Copying". If not, you can get one
- from the Perl distribution or else write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
-
-CHANGES
-
-New since alpha3
- Anonymous subs work properly with C and CC.
- Heuristics for forcing compilation of apparently unused subs/methods.
- Subs which use the AutoLoader module are forcibly loaded at compile-time.
- Slightly faster compilation.
- Handles slightly more complex code within a BEGIN { }.
- Minor bug fixes.
-
-New since alpha2
- CC backend now supports ".." and s//e.
- Xref backend generates cross-reference reports
- Cleanups to fix benign but irritating "-w" warnings
- Minor cxstack fix
-New since alpha1
- Working CC backend
- Shared globs and pre-initialised hash support
- Some XSUB support
- Assorted bug fixes
-
-INSTALLATION
-
-(1) You need perl5.002 or later.
-
-(2) If you want to compile and run programs with the C or CC backends
-which undefine (or redefine) subroutines, then you need to apply a
-one-line patch to perl itself. One or two of the programs in perl's
-own test suite do this. The patch is in file op.patch. It prevents
-perl from calling free() on OPs with the magic sequence number (U16)-1.
-The compiler declares all OPs as static structures and uses that magic
-sequence number.
-
-(3) Type
- perl Makefile.PL
-to write a personalised Makefile for your system. If you want the
-bytecode modules to support reading bytecode from strings (instead of
-just from files) then add the option
- -DINDIRECT_BGET_MACROS
-into the middle of the definition of the CCCMD macro in the Makefile.
-Your C compiler may need to be able to cope with Standard C for this.
-I haven't tested this option yet with an old pre-Standard compiler.
-
-(4) If your platform supports dynamic loading then just type
- make
-and you can then use
- perl -Iblib/arch -MO=foo bar
-to use the compiler modules (see later for details).
-If you need/want instead to make a statically linked perl which
-contains the appropriate modules, then type
- make perl
- make byteperl
-and you can then use
- ./perl -MO=foo bar
-to use the compiler modules.
-In both cases, the byteperl executable is required for running standalone
-bytecode programs. It is *not* a standard perl+XSUB perl executable.
-
-USAGE
-
-As of the alpha3 release, the Bytecode, C and CC backends are now all
-functional enough to compile almost the whole of the main perl test
-suite. In the case of the CC backend, any failures are all due to
-differences and/or known bugs documented below. See the file TESTS.
-In the following examples, you'll need to replace "perl" by
- perl -Iblib/arch
-if you have built the extensions for a dynamic loading platform but
-haven't installed the extensions completely. You'll need to replace
-"perl" by
- ./perl
-if you have built the extensions into a statically linked perl binary.
-
-(1) To compile perl program foo.pl with the C backend, do
- perl -MO=C,-ofoo.c foo.pl
-Then use the cc_harness perl program to compile the resulting C source:
- perl cc_harness -O2 -o foo foo.c
-
-If you are using a non-ANSI pre-Standard C compiler that can't handle
-pre-declaring static arrays, then add -DBROKEN_STATIC_REDECL to the
-options you use:
- perl cc_harness -O2 -o foo -DBROKEN_STATIC_REDECL foo.c
-If you are using a non-ANSI pre-Standard C compiler that can't handle
-static initialisation of structures with union members then add
--DBROKEN_UNION_INIT to the options you use. If you want command line
-arguments passed to your executable to be interpreted by perl (e.g. -Dx)
-then compile foo.c with -DALLOW_PERL_OPTIONS. Otherwise, all command line
-arguments passed to foo will appear directly in @ARGV. The resulting
-executable foo is the compiled version of foo.pl. See the file NOTES for
-extra options you can pass to -MO=C.
-
-There are some constraints on the contents on foo.pl if you want to be
-able to compile it successfully. Some problems can be fixed fairly easily
-by altering foo.pl; some problems with the compiler are known to be
-straightforward to solve and I'll do so soon. The file Todo lists a
-number of known problems. See the XSUB section lower down for information
-about compiling programs which use XSUBs.
-
-(2) To compile foo.pl with the CC backend (which generates actual
-optimised C code for the execution path of your perl program), use
- perl -MO=CC,-ofoo.c foo.pl
-
-and proceed just as with the C backend. You should almost certainly
-use an option such as -O2 with the subsequent cc_harness invocation
-so that your C compiler uses optimisation. The C code generated by
-the Perl compiler's CC backend looks ugly to humans but is easily
-optimised by C compilers.
-
-To make the most of this compiler backend, you need to tell the
-compiler when you're using int or double variables so that it can
-optimise appropriately (although this part of the compiler is the most
-buggy). You currently do that by naming lexical variables ending in
-"_i" for ints, "_d" for doubles, "_ir" for int "register" variables or
-"_dr" for double "register" variables. Here "register" is a promise
-that you won't pass a reference to the variable into a sub which then
-modifies the variable. The compiler ought to catch attempts to use
-"\$i" just as C compilers catch attempts to do "&i" for a register int
-i but it doesn't at the moment. Bugs in the CC backend may make your
-program fail in mysterious ways and give wrong answers rather than just
-crash in boring ways. But, hey, this is an alpha release so you knew
-that anyway. See the XSUB section lower down for information about
-compiling programs which use XSUBs.
-
-If your program uses classes which define methods (or other subs which
-are not exported and not apparently used until runtime) then you'll
-need to use -u compile-time options (see the NOTES file) to force the
-subs to be compiled. Future releases will probably default the other
-way, do more auto-detection and provide more fine-grained control.
-
-Since compiled executables need linking with libperl, you may want
-to turn libperl.a into a shared library if your platform supports
-it. For example, with Digital UNIX, do something like
- ld -shared -o libperl.so -all libperl.a -none -lc
-and with Linux/ELF, rebuild the perl .c files with -fPIC (and I
-also suggest -fomit-frame-pointer for Linux on Intel architetcures),
-do "make libperl.a" and then do
- gcc -shared -Wl,-soname,libperl.so.5 -o libperl.so.5.3 `ar t libperl.a`
-and then
- # cp libperl.so.5.3 /usr/lib
- # cd /usr/lib
- # ln -s libperl.so.5.3 libperl.so.5
- # ln -s libperl.so.5 libperl.so
- # ldconfig
-When you compile perl executables with cc_harness, append -L/usr/lib
-otherwise the -L for the perl source directory will override it. For
-example,
- perl -Iblib/arch -MO=CC,-O2,-ofoo3.c foo3.bench
- perl cc_harness -o foo3 -O2 foo3.c -L/usr/lib
- ls -l foo3
- -rwxr-xr-x 1 mbeattie xzdg 11218 Jul 1 15:28 foo3
-You'll probably also want to link your main perl executable against
-libperl.so; it's nice having an 11K perl executable.
-
-(3) To compile foo.pl into bytecode do
- perl -MO=Bytecode,-ofoo foo.pl
-To run the resulting bytecode file foo as a standalone program, you
-use the program byteperl which should have been built along with the
-extensions.
- ./byteperl foo
-Any extra arguments are passed in as @ARGV; they are not interpreted
-as perl options. If you want to load chunks of bytecode into an already
-running perl program then use the -m option and investigate the
-byteload_fh and byteload_string functions exported by the B module.
-See the NOTES file for details of these and other options (including
-optimisation options and ways of getting at the intermediate "assembler"
-code that the Bytecode backend uses).
-
-(3) There are little Bourne shell scripts and perl programs to aid with
-some common operations: assemble, disassemble, run_bytecode_test,
-run_test, cc_harness, test_harness, test_harness_bytecode.
-
-(4) Walk the op tree in execution order printing terse info about each op
- perl -MO=Terse,exec foo.pl
-
-(5) Walk the op tree in syntax order printing lengthier debug info about
-each op. You can also append ",exec" to walk in execution order, but the
-formatting is designed to look nice with Terse rather than Debug.
- perl -MO=Debug foo.pl
-
-(6) Produce a cross-reference report of the line numbers at which all
-variables, subs and formats are defined and used.
- perl -MO=Xref foo.pl
-
-XSUBS
-
-The C and CC backends can successfully compile some perl programs which
-make use of XSUB extensions. [I'll add more detail to this section in a
-later release.] As a prerequisite, such extensions must not need to do
-anything in their BOOT: section which needs to be done at runtime rather
-than compile time. Normally, the only code in the boot_Foo() function is
-a list of newXS() calls which xsubpp puts there and the compiler handles
-saving those XS subs itself. For each XSUB used, the C and CC compiler
-will generate an initialiser in their C output which refers to the name
-of the relevant C function (XS_Foo_somesub). What is not yet automated
-is the necessary commands and cc command-line options (e.g. via
-"perl cc_harness") which link against the extension libraries. For now,
-you need the XSUB extension to have installed files in the right format
-for using as C libraries (e.g. Foo.a or Foo.so). As the Foo.so files (or
-your platform's version) aren't suitable for linking against, you will
-have to reget the extension source and rebuild it as a static extension
-to force the generation of a suitable Foo.a file. Then you need to make
-a symlink (or copy or rename) of that file into a libFoo.a suitable for
-cc linking. Then add the appropriate -L and -l options to your
-"perl cc_harness" command line to find and link against those libraries.
-You may also need to fix up some platform-dependent environment variable
-to ensure that linked-against .so files are found at runtime too.
-
-DIFFERENCES
-
-The result of running a compiled Perl program can sometimes be different
-from running the same program with standard perl. Think of the compiler
-as having a slightly different implementation of the language Perl.
-Unfortunately, since Perl has had a single implementation until now,
-there are no formal standards or documents defining what behaviour is
-guaranteed of Perl the language and what just "happens to work".
-Some of the differences below are almost impossible to change because of
-the way the compiler works. Others can be changed to produce "standard"
-perl behaviour if it's deemed proper and the resulting performance hit
-is accepted. I'll use "standard perl" to mean the result of running a
-Perl program using the perl executable from the perl distribution.
-I'll use "compiled Perl program" to mean running an executable produced
-by this compiler kit ("the compiler") with the CC backend.
-
-Loops
- Standard perl calculates the target of "next", "last", and "redo"
- at run-time. The compiler calculates the targets at compile-time.
- For example, the program
-
- sub skip_on_odd { next NUMBER if $_[0] % 2 }
- NUMBER: for ($i = 0; $i < 5; $i++) {
- skip_on_odd($i);
- print $i;
- }
-
- produces the output
- 024
- with standard perl but gives a compile-time error with the compiler.
-
-Context of ".."
- The context (scalar or array) of the ".." operator determines whether
- it behaves as a range or a flip/flop. Standard perl delays until
- runtime the decision of which context it is in but the compiler needs
- to know the context at compile-time. For example,
- @a = (4,6,1,0,0,1);
- sub range { (shift @a)..(shift @a) }
- print range();
- while (@a) { print scalar(range()) }
- generates the output
- 456123E0
- with standard Perl but gives a compile-time error with compiled Perl.
-
-Arithmetic
- Compiled Perl programs use native C arithemtic much more frequently
- than standard perl. Operations on large numbers or on boundary
- cases may produce different behaviour.
-
-Deprecated features
- Features of standard perl such as $[ which have been deprecated
- in standard perl since version 5 was released have not been
- implemented in the compiler.
-
-Others
- I'll add to this list as I remember what they are.
-
-BUGS
-
-Here are some things which may cause the compiler problems.
-
-The following render the compiler useless (without serious hacking):
-* Use of the DATA filehandle (via __END__ or __DATA__ tokens)
-* Operator overloading with %OVERLOAD
-* The (deprecated) magic array-offset variable $[ does not work
-* The following operators are not yet implemented for CC
- goto
- sort with a non-default comparison (i.e. a named sub or inline block)
-* You can't use "last" to exit from a non-loop block.
-
-The following may give significant problems:
-* BEGIN blocks containing complex initialisation code
-* Code which is only ever referred to at runtime (e.g. via eval "..." or
- via method calls): see the -u option for the C and CC backends.
-* Run-time lookups of lexical variables in "outside" closures
-
-The following may cause problems (not thoroughly tested):
-* Dependencies on whether values of some "magic" Perl variables are
- determined at compile-time or runtime.
-* For the C and CC backends: compile-time strings which are longer than
- your C compiler can cope with in a single line or definition.
-* Reliance on intimate details of global destruction
-* For the Bytecode backend: high -On optimisation numbers with code
- that has complex flow of control.
-* Any "-w" option in the first line of your perl program is seen and
- acted on by perl itself before the compiler starts. The compiler
- itself then runs with warnings turned on. This may cause perl to
- print out warnings about the compiler itself since I haven't tested
- it thoroughly with warnings turned on.
-
-There is a terser but more complete list in the Todo file.
-
-Malcolm Beattie
-2 September 1996
diff --git a/contrib/perl5/ext/B/TESTS b/contrib/perl5/ext/B/TESTS
deleted file mode 100644
index e050f6c..0000000
--- a/contrib/perl5/ext/B/TESTS
+++ /dev/null
@@ -1,78 +0,0 @@
-Test results from compiling t/*/*.t
- C Bytecode CC
-
-base/cond.t OK ok OK
-base/if.t OK ok OK
-base/lex.t OK ok OK
-base/pat.t OK ok OK
-base/term.t OK ok OK
-cmd/elsif.t OK ok OK
-cmd/for.t OK ok ok 1, 2, 3, panic: pp_iter
-cmd/mod.t OK ok ok
-cmd/subval.t OK ok 1..34, not ok 27,28 (simply
- because filename changes).
-cmd/switch.t OK ok ok
-cmd/while.t OK ok ok
-io/argv.t OK ok ok
-io/dup.t OK ok ok
-io/fs.t OK ok ok
-io/inplace.t OK ok ok
-io/pipe.t OK ok ok with -umain
-io/print.t OK ok ok
-io/tell.t OK ok ok
-op/append.t OK ok OK
-op/array.t OK ok 1..36, not ok 7,10 (no $[)
-op/auto.t OK ok OK
-op/chop.t OK ok OK
-op/cond.t OK ok OK
-op/delete.t OK ok OK
-op/do.t OK ok OK
-op/each.t OK ok OK
-op/eval.t OK ok ok 1-6 of 16 then exits
-op/exec.t OK ok OK
-op/exp.t OK ok OK
-op/flip.t OK ok OK
-op/fork.t OK ok OK
-op/glob.t OK ok OK
-op/goto.t OK ok 1..9, Can't find label label1.
-op/groups.t OK (s/ucb/bin/ under Linux) OK 1..0 for now.
-op/index.t OK ok OK
-op/int.t OK ok OK
-op/join.t OK ok OK
-op/list.t OK ok OK
-op/local.t OK ok OK
-op/magic.t OK ok OK
-op/misc.t no DATA filehandle so succeeds trivially with 1..0
-op/mkdir.t OK ok OK
-op/my.t OK ok OK
-op/oct.t OK ok OK (C large const warnings)
-op/ord.t OK ok OK
-op/overload.t Mostly not ok Mostly not ok C errors.
-op/pack.t OK ok OK
-op/pat.t omit 26 (reset) ok [lots of memory for compile]
-op/push.t OK ok OK
-op/quotemeta.t OK ok OK
-op/rand.t OK ok
-op/range.t OK ok OK
-op/read.t OK ok OK
-op/readdir.t OK ok OK (substcont works too)
-op/ref.t omits "ok 40" (lex destruction) ok (Bytecode)
- CC: need -u for OBJ,BASEOBJ,
- UNIVERSAL,WHATEVER,main.
- 1..41, ok1-33,36-38,
- then ok 41, ok 39.DESTROY probs
-op/regexp.t OK ok ok (trivially all eval'd)
-op/repeat.t OK ok ok
-op/sleep.t OK ok ok
-op/sort.t OK ok 1..10, ok 1, Out of memory!
-op/split.t OK ok ok
-op/sprintf.t OK ok ok
-op/stat.t OK ok ok
-op/study.t OK ok ok
-op/subst.t OK ok ok
-op/substr.t OK ok ok1-22 except 7-9,11 (all $[)
-op/time.t OK ok ok
-op/undef.t omit 21 ok ok
-op/unshift.t OK ok ok
-op/vec.t OK ok ok
-op/write.t not ok 3 (no CvOUTSIDE lex from runtime eval). CC: 1..3, hang
diff --git a/contrib/perl5/ext/B/Todo b/contrib/perl5/ext/B/Todo
deleted file mode 100644
index 495be2e..0000000
--- a/contrib/perl5/ext/B/Todo
+++ /dev/null
@@ -1,37 +0,0 @@
-* Fixes
-
-CC backend: goto, sort with non-default comparison. last for non-loop blocks.
-Version checking
-improve XSUB handling (both static and dynamic)
-sv_magic can do SvREFCNT_inc(obj) which messes up precalculated refcounts
-allocation of XPV[INAHC]V structures needs fixing: Perl tries to free
-them whereas the compiler expects them to be linked to a xpv[inahc]v_root
-list the same as X[IPR]V structures.
-ref counts
-perl_parse replacement
-fix cstring for long strings
-compile-time initialisation of AvARRAYs
-signed/unsigned problems with NV (and IV?) initialisation and elsewhere?
-CvOUTSIDE for ordinary subs
-DATA filehandle for standalone Bytecode program (easy)
-DATA filehandle for multiple bytecode-compiled modules (harder)
-DATA filehandle for C-compiled program (yet harder)
-
-* Features
-
-type checking
-compile time v. runtime initialisation
-save PMOPs in compiled form
-selection of what to dump
-options for cutting out line info etc.
-comment output
-shared constants
-module dependencies
-
-* Optimisations
-collapse LISTOPs to UNOPs or BASEOPs
-compile-time qw(), constant subs
-global analysis of variables, type hints etc.
-demand-loaded bytecode (leader of each basic block replaced by an op
-which loads in bytecode for its block)
-fast sub calls for CC backend
diff --git a/contrib/perl5/ext/B/defsubs_h.PL b/contrib/perl5/ext/B/defsubs_h.PL
deleted file mode 100644
index da6566b..0000000
--- a/contrib/perl5/ext/B/defsubs_h.PL
+++ /dev/null
@@ -1,42 +0,0 @@
-# Do not remove the following line; MakeMaker relies on it to identify
-# this file as a template for defsubs.h
-# Extracting defsubs.h (with variable substitutions)
-#!perl
-my ($out) = __FILE__ =~ /(^.*)\.PL/i;
-$out =~ s/_h$/.h/;
-open(OUT,">$out") || die "Cannot open $file:$!";
-print "Extracting $out...\n";
-foreach my $const (qw(
- AVf_REAL
- HEf_SVKEY
- SVf_READONLY SVTYPEMASK
- GVf_IMPORTED_AV GVf_IMPORTED_HV
- GVf_IMPORTED_SV GVf_IMPORTED_CV
- CVf_METHOD CVf_LOCKED CVf_LVALUE
- SVf_IOK SVf_IVisUV SVf_NOK SVf_POK
- SVf_ROK SVp_IOK SVp_POK SVp_NOK
- ))
- {
- doconst($const);
- }
-foreach my $file (qw(op.h cop.h))
- {
- my $path = $^O eq 'MacOS' ? ":::$file" : "../../$file";
- open(OPH,"$path") || die "Cannot open $path:$!";
- while (<OPH>)
- {
- doconst($1) if (/#define\s+(\w+)\s+([\(\)\|\dx]+)\s*(?:$|\/\*)/);
- }
- close(OPH);
- }
-close(OUT);
-
-sub doconst
-{
- my $sym = shift;
- my $l = length($sym);
- print OUT <<"END";
- newCONSTSUB(stash,"$sym",newSViv($sym));
- av_push(export_ok,newSVpvn("$sym",$l));
-END
-}
diff --git a/contrib/perl5/ext/B/ramblings/cc.notes b/contrib/perl5/ext/B/ramblings/cc.notes
deleted file mode 100644
index 47bd65a..0000000
--- a/contrib/perl5/ext/B/ramblings/cc.notes
+++ /dev/null
@@ -1,32 +0,0 @@
-At entry to each basic block, the following can be assumed (and hence
-must be forced where necessary at the end of each basic block):
-
-The shadow stack @stack is empty.
-For each lexical object in @pad, VALID_IV holds for each T_INT,
-VALID_DOUBLE holds for each T_DOUBLE and VALID_SV holds otherwise.
-The C shadow variable sp holds the stack pointer (not necessarily stack_sp).
-
-write_back_stack
- Writes the contents of the shadow stack @stack back to the real stack.
- A write-back of each object in the stack is forced so that its
- backing SV contains the right value and that SV is then pushed onto the
- real stack. On return, @stack is empty.
-
-write_back_lexicals
- Forces a write-back (i.e. achieves VALID_SV), where necessary, for each
- lexical object in @pad. Objects with the TEMPORARY flag are skipped. If
- write_back_lexicals is called with an (optional) argument, then it is
- taken to be a bitmask of more flags: any lexical object with one of those
- flags set is also skipped and not written back to its SV.
-
-invalidate_lexicals($avoid)
- The VALID_INT and VALID_DOUBLE flags are turned off for each lexical
- object in @pad whose flags field doesn't overlap with $avoid.
-
-reload_lexicals
- For each necessary lexical object in @pad, makes sure that VALID_IV
- holds for objects of type T_INT, VALID_DOUBLE holds for objects for
- type T_DOUBLE, and VALID_SV holds for other objects. An object is
- considered for reloading if its flags field does not overlap with the
- (optional) argument passed to reload_lexicals.
-
diff --git a/contrib/perl5/ext/B/ramblings/curcop.runtime b/contrib/perl5/ext/B/ramblings/curcop.runtime
deleted file mode 100644
index 9b8b7d5..0000000
--- a/contrib/perl5/ext/B/ramblings/curcop.runtime
+++ /dev/null
@@ -1,39 +0,0 @@
-PP code uses of curcop
-----------------------
-
-pp_rv2gv
- when a new glob is created for an OPpLVAL_INTRO,
- curcop->cop_line is stored as GvLINE() in the new GP.
-pp_bless
- curcop->cop_stash is used as the stash in the one-arg form of bless
-
-pp_repeat
- tests (curcop != &compiling) to warn "Can't x= to readonly value"
-
-pp_pos
-pp_substr
-pp_index
-pp_rindex
-pp_aslice
-pp_lslice
-pp_splice
- curcop->cop_arybase
-
-pp_sort
- curcop->cop_stash used to determine whether to gv_fetchpv $a and $b
-
-pp_caller
- tests (curcop->cop_stash == debstash) to determine whether
- to set DB::args
-
-pp_reset
- resets vars in curcop->cop_stash
-
-pp_dbstate
- sets curcop = (COP*)op
-
-doeval
- compiles into curcop->cop_stash
-
-pp_nextstate
- sets curcop = (COP*)op
diff --git a/contrib/perl5/ext/B/ramblings/flip-flop b/contrib/perl5/ext/B/ramblings/flip-flop
deleted file mode 100644
index e08333d..0000000
--- a/contrib/perl5/ext/B/ramblings/flip-flop
+++ /dev/null
@@ -1,54 +0,0 @@
-PP(pp_range)
-{
- if (GIMME == G_ARRAY)
- return NORMAL;
- if (SvTRUEx(PAD_SV(PL_op->op_targ)))
- return cLOGOP->op_other;
- else
- return NORMAL;
-}
-
-pp_range is a LOGOP.
-In list context, it just returns op_next.
-In scalar context it checks the truth of targ and returns
-op_other if true, op_next if false.
-
-flip is an UNOP.
-It "looks after" its child which is always a pp_range LOGOP.
-In list context, it just returns the child's op_other.
-In scalar context, there are three possible outcomes:
- (1) set child's targ to 1, our targ to 1 and return op_next.
- (2) set child's targ to 1, our targ to 0, sp-- and return child's op_other.
- (3) Blank targ and TOPs and return op_next.
-Case 1 happens for a "..." with a matching lineno... or true TOPs.
-Case 2 happens for a ".." with a matching lineno... or true TOPs.
-Case 3 happens for a non-matching lineno or false TOPs.
-
- $a = lhs..rhs;
-
- ,-------> range
- ^ / \
- | true/ \false
- | / \
- first| lhs rhs
- | \ first /
- ^--- flip <----- flop
- \ /
- \ /
- sassign
-
-
-/* range */
-if (SvTRUE(curpad[op->op_targ]))
- goto label(op_other);
-/* op_next */
-...
-/* flip */
-/* For "..." returns op_next. For ".." returns op_next or op_first->op_other */
-/* end of basic block */
-goto out;
-label(range op_other):
-...
-/* flop */
-out:
-...
diff --git a/contrib/perl5/ext/B/ramblings/magic b/contrib/perl5/ext/B/ramblings/magic
deleted file mode 100644
index e41930a..0000000
--- a/contrib/perl5/ext/B/ramblings/magic
+++ /dev/null
@@ -1,93 +0,0 @@
-sv_magic()
-----------
-av.c
-av_store()
- Storing a non-undef element into an SMAGICAL array, av,
- assigns the equivalent lowercase form of magic (of the first
- MAGIC in the chain) to the value (with obj = av, name = 0 and
- namlen = array index).
-
-gv.c
-gv_init()
- Initialising gv assigns '*' magic to it with obj = gv, name =
- GvNAME and namlen = GvNAMELEN.
-gv_fetchpv()
- @ISA gets 'I' magic with obj = gv, zero name and namlen.
- %OVERLOAD gets 'A' magic with obj = gv, zero name and namlen.
- $1 to $9, $&, $`, $', $+ get '\0' magic with obj = gv,
- name = GvNAME and namlen = len ( = 1 presumably).
-Gv_AMupdate()
- Stashes for overload magic seem to get 'c' magic with obj = 0,
- name = &amt and namlen = sizeof(amt).
-hv_magic(hv, gv, how)
- Gives magic how to hv with obj = gv and zero name and namlen.
-
-mg.c
-mg_copy(sv, nsv, key, klen)
- Traverses the magic chain of sv. Upper case forms of magic
- (only) are copied across to nsv, preserving obj but using
- name = key and namlen = klen.
-magic_setpos()
- LvTARG of a PVLV gets 'g' magic with obj = name = 0 and namlen = pos.
-
-op.c
-mod()
- PVLV operators give magic to their targs with
- obj = name = namlen = 0. OP_POS gives '.', OP_VEC gives 'v'
- and OP_SUBSTR gives 'x'.
-
-perl.c
-magicname(sym, name, namlen)
- Fetches/creates a GV with name sym and gives it '\0' magic
- with obj = gv, name and namlen as passed.
-init_postdump_symbols()
- Elements of the environment get given SVs with 'e' magic.
- obj = sv and name and namlen point to the actual string
- within env.
-
-pp.c
-pp_av2arylen()
- $#foo gives '#' magic to the new SV with obj = av and
- name = namlen = 0.
-pp_study()
- SV gets 'g' magic with obj = name = namlen = 0.
-pp_substr()
- PVLV gets 'x' magic with obj = name = namlen = 0.
-pp_vec()
- PVLV gets 'x' magic with obj = name = namlen = 0.
-
-pp_hot.c
-pp_match()
- m//g gets 'g' magic with obj = name = namlen = 0.
-
-pp_sys.c
-pp_tie()
- sv gets magic with obj = sv and name = namlen = 0.
- If an HV or an AV, it gets 'P' magic, otherwise 'q' magic.
-pp_dbmopen()
- 'P' magic for the HV just as with pp_tie().
-pp_sysread()
- If tainting, the buffer SV gets 't' magic with
- obj = name = namlen = 0.
-
-sv.c
-sv_setsv()
- Doing sv_setsv(dstr, gv) gives '*' magic to dstr with
- obj = dstr, name = GvNAME, namlen = GvNAMELEN.
-
-util.c
-fbm_compile()
- The PVBM gets 'B' magic with obj = name = namlen = 0 and SvVALID
- is set to indicate that the Boyer-Moore table is valid.
- magic_setbm() just clears the SvVALID flag.
-
-hv_magic()
-----------
-
-gv.c
-gv_fetchfile()
- With perldb, the HV of a gvfile gv gets 'L' magic with obj = gv.
-gv_fetchpv()
- %SIG gets 'S' magic with obj = siggv.
-init_postdump_symbols()
- %ENV gets 'E' magic with obj = envgv.
diff --git a/contrib/perl5/ext/B/ramblings/reg.alloc b/contrib/perl5/ext/B/ramblings/reg.alloc
deleted file mode 100644
index 7fd69f2..0000000
--- a/contrib/perl5/ext/B/ramblings/reg.alloc
+++ /dev/null
@@ -1,32 +0,0 @@
-while ($i--) {
- foo();
-}
-exit
-
- PP code if i an int register if i an int but not a
- (i.e. can't be register (i.e. can be
- implicitly invalidated) implicitly invalidated)
- nextstate
- enterloop
-
-
- loop:
- gvsv GV (0xe6078) *i validates i validates i
- postdec invalidates $i invalidates $i
- and if_false goto out;
- i valid; $i invalid i valid; $i invalid
-
- i valid; $i invalid i valid; $i invalid
- nextstate
- pushmark
- gv GV (0xe600c) *foo
- entersub validates $i; invals i
-
- unstack
- goto loop:
-
- i valid; $i invalid
- out:
- leaveloop
- nextstate
- exit
diff --git a/contrib/perl5/ext/B/ramblings/runtime.porting b/contrib/perl5/ext/B/ramblings/runtime.porting
deleted file mode 100644
index d58b011..0000000
--- a/contrib/perl5/ext/B/ramblings/runtime.porting
+++ /dev/null
@@ -1,357 +0,0 @@
-Notes on porting the perl runtime PP engine.
-Importance: 1 = who cares?, 10 = vital
-Difficulty: 1 = trivial, 10 = very difficult. Level assumes a
-reasonable implementation of the SV and OP API already ported.
-
-OP Import Diff Comments
-null 10 1
-stub 10 1
-scalar 10 1
-pushmark 10 1 PUSHMARK
-wantarray 7 3 cxstack, dopoptosub
-const 10 1
-gvsv 10 1 save_scalar
-gv 10 1
-gelem 3 3
-padsv 10 2 SAVECLEARSV, provide_ref
-padav 10 2
-padhv 10 2
-padany 1 1
-pushre 7 3 pushes an op. Blech.
-rv2gv 6 5
-rv2sv 10 4
-av2arylen 7 3 sv_magic
-rv2cv 8 5 sv_2cv
-anoncode 7 6 cv_clone
-prototype 4 4 sv_2cv
-refgen 8 3
-srefgen 8 2
-ref 8 3
-bless 7 3
-backtick 5 4
-glob 5 2 do_readline
-readline 8 2 do_readline
-rcatline 8 2
-regcmaybe 8 1
-regcreset 8 1
-regcomp 8 9 pregcomp
-match 8 10
-qr 8 1
-subst 8 10
-substcont 8 7
-trans 7 4 do_trans
-sassign 10 3 mg_find, SvSETMAGIC
-aassign 10 5
-chop 8 3 do_chop
-schop 8 3 do_chop
-chomp 8 3 do_chomp
-schomp 8 3 do_chomp
-defined 10 2
-undef 10 3
-study 4 5
-pos 8 3 PVLV, mg_find
-preinc 10 2 sv_inc, SvSETMAGIC
-i_preinc
-predec 10 2 sv_dec, SvSETMAGIC
-i_predec
-postinc 10 2 sv_dec, SvSETMAGIC
-i_postinc
-postdec 10 2 sv_dec, SvSETMAGIC
-i_postdec
-pow 10 1
-multiply 10 1
-i_multiply 10 1
-divide 10 2
-i_divide 10 1
-modulo 10 2
-i_modulo 10 1
-repeat 6 4
-add 10 1
-i_add 10 1
-subtract 10 1
-i_subtract 10 1
-concat 10 2 mg_get
-stringify 10 2 sv_setpvn
-left_shift 10 1
-right_shift 10 1
-lt 10 1
-i_lt 10 1
-gt 10 1
-i_gt 10 1
-le 10 1
-i_le 10 1
-ge 10 1
-i_ge 10 1
-eq 10 1
-i_eq 10 1
-ne 10 1
-i_ne 10 1
-ncmp 10 1
-i_ncmp 10 1
-slt 10 2
-sgt 10 2
-sle 10 2
-sge 10 2
-seq 10 2 sv_eq
-sne 10 2
-scmp 10 2
-bit_and 10 2
-bit_xor 10 2
-bit_or 10 2
-negate 10 3
-i_negate 10 1
-not 10 1
-complement 10 3
-atan2 6 1
-sin 6 1
-cos 6 1
-rand 5 2
-srand 5 2
-exp 6 1
-log 6 2
-sqrt 6 2
-int 10 2
-hex 9 2
-oct 9 2
-abs 10 1
-length 10 1
-substr 10 4 PVLV
-vec 5 4
-index 9 3
-rindex 9 3
-sprintf 9 4 do_sprintf
-formline 6 7
-ord 6 2
-chr 6 2
-crypt 3 2
-ucfirst 6 2
-lcfirst 6 2
-uc 6 2
-lc 6 2
-quotemeta 6 3
-rv2av 10 3 save_svref, mg_get, save_ary
-aelemfast 10 2 av_fetch
-aelem 10 3
-aslice 9 4
-each 10 3 hv_iternext
-values 10 3 do_kv
-keys 10 3 do_kv
-delete 10 3
-exists 10 3
-rv2hv 10 3 save_svref, mg_get, save_ary, do_kv
-helem 10 3 save_svref, provide_ref
-hslice 9 4
-unpack 9 6 lengthy
-pack 9 6 lengthy
-split 9 9
-join 10 4 do_join
-list 10 2
-lslice 9 4
-anonlist 10 2
-anonhash 10 3
-splice 9 6
-push 10 2
-pop 10 2
-shift 10 2
-unshift 10 2
-sort 6 7
-reverse 9 4
-grepstart 6 5 modifies flow of control
-grepwhile 6 5 modifies flow of control
-mapstart 1 1
-mapwhile 6 5 modifies flow of control
-range 7 3 modifies flow of control
-flip 7 4 modifies flow of control
-flop 7 4 modifies flow of control
-and 10 3 modifies flow of control
-or 10 3 modifies flow of control
-xor
-cond_expr 10 3 modifies flow of control
-andassign 7 3 modifies flow of control
-orassign 7 3 modifies flow of control
-method 8 5
-entersub 10 7
-leavesub 10 5
-leavesublv
-caller 2 8
-warn 9 3
-die 9 3
-reset 2 2
-lineseq 1 1
-nextstate 10 1 Update stack_sp from cxstack. FREETMPS.
-dbstate 3 7
-unstack
-enter 10 3 cxstack, ENTER, SAVETMPS, PUSHBLOCK
-leave 10 3 cxstack, SAVETMPS, LEAVE, POPBLOCK
-scope 1 1
-enteriter 9 4 cxstack
-iter 9 3 cxstack
-enterloop 10 4
-leaveloop 10 4
-return 10 5
-last 9 6
-next 9 6
-redo 9 6
-dump 1 9 pp_goto
-goto 6 9
-exit 9 2 my_exit
-open 9 5 do_open
-close 9 3 do_close
-pipe_op 7 4
-fileno 9 2
-umask 4 2
-binmode 4 2
-tie 5 5 pp_entersub
-untie 5 2 sv_unmagic
-tied 5 2
-dbmopen 4 5
-dbmclose 4 2
-sselect 4 4
-select 7 3
-getc 7 2
-read 8 2 pp_sysread
-enterwrite 4 4 doform
-leavewrite 4 5
-prtf 4 4 do_sprintf
-print 8 6
-sysopen 8 2
-sysseek 8 2
-sysread 8 4
-syswrite 8 4 pp_send
-send 8 4
-recv 8 4 pp_sysread
-eof 9 2
-tell 9 3
-seek 9 2
-truncate 8 3
-fcntl 8 4 pp_ioctl
-ioctl 8 4
-flock 8 2
-socket 5 3
-sockpair 5 3
-bind 5 3
-connect 5 3
-listen 5 3
-accept 5 3
-shutdown 5 2
-gsockopt 5 3 pp_ssockopt
-ssockopt 5 3
-getsockname 5 3 pp_getpeername
-getpeername 5 3
-lstat 5 4 pp_stat
-stat 5 4 lengthy
-ftrread 5 2 cando
-ftrwrite 5 2 cando
-ftrexec 5 2 cando
-fteread 5 2 cando
-ftewrite 5 2 cando
-fteexec 5 2 cando
-ftis 5 2 cando
-fteowned 5 2 cando
-ftrowned 5 2 cando
-ftzero 5 2 cando
-ftsize 5 2 cando
-ftmtime 5 2 cando
-ftatime 5 2 cando
-ftctime 5 2 cando
-ftsock 5 2 cando
-ftchr 5 2 cando
-ftblk 5 2 cando
-ftfile 5 2 cando
-ftdir 5 2 cando
-ftpipe 5 2 cando
-ftlink 5 2 cando
-ftsuid 5 2 cando
-ftsgid 5 2 cando
-ftsvtx 5 2 cando
-fttty 5 2 cando
-fttext 5 4
-ftbinary 5 4 fttext
-chdir
-chown
-chroot
-unlink
-chmod
-utime
-rename
-link
-symlink
-readlink
-mkdir
-rmdir
-open_dir
-readdir
-telldir
-seekdir
-rewinddir
-closedir
-fork
-wait
-waitpid
-system
-exec
-kill
-getppid
-getpgrp
-setpgrp
-getpriority
-setpriority
-time
-tms
-localtime
-gmtime
-alarm
-sleep
-shmget
-shmctl
-shmread
-shmwrite
-msgget
-msgctl
-msgsnd
-msgrcv
-semget
-semctl
-semop
-require 6 9 doeval
-dofile 6 9 doeval
-entereval 6 9 doeval
-leaveeval 6 5
-entertry 7 4 modifies flow of control
-leavetry 7 3
-ghbyname
-ghbyaddr
-ghostent
-gnbyname
-gnbyaddr
-gnetent
-gpbyname
-gpbynumber
-gprotoent
-gsbyname
-gsbyport
-gservent
-shostent
-snetent
-sprotoent
-sservent
-ehostent
-enetent
-eprotoent
-eservent
-gpwnam
-gpwuid
-gpwent
-spwent
-epwent
-ggrnam
-ggrgid
-ggrent
-sgrent
-egrent
-getlogin
-syscall
-lock 6 1
-threadsv 6 2 unused if not USE_THREADS
-setstate 1 1 currently unused anywhere
-method_named 10 2
diff --git a/contrib/perl5/ext/B/typemap b/contrib/perl5/ext/B/typemap
deleted file mode 100644
index bafba1c..0000000
--- a/contrib/perl5/ext/B/typemap
+++ /dev/null
@@ -1,69 +0,0 @@
-TYPEMAP
-
-B::OP T_OP_OBJ
-B::UNOP T_OP_OBJ
-B::BINOP T_OP_OBJ
-B::LOGOP T_OP_OBJ
-B::LISTOP T_OP_OBJ
-B::PMOP T_OP_OBJ
-B::SVOP T_OP_OBJ
-B::PADOP T_OP_OBJ
-B::PVOP T_OP_OBJ
-B::CVOP T_OP_OBJ
-B::LOOP T_OP_OBJ
-B::COP T_OP_OBJ
-
-B::SV T_SV_OBJ
-B::PV T_SV_OBJ
-B::IV T_SV_OBJ
-B::NV T_SV_OBJ
-B::PVMG T_SV_OBJ
-B::PVLV T_SV_OBJ
-B::BM T_SV_OBJ
-B::RV T_SV_OBJ
-B::GV T_SV_OBJ
-B::CV T_SV_OBJ
-B::HV T_SV_OBJ
-B::AV T_SV_OBJ
-B::IO T_SV_OBJ
-
-B::MAGIC T_MG_OBJ
-SSize_t T_IV
-STRLEN T_IV
-PADOFFSET T_UV
-
-INPUT
-T_OP_OBJ
- if (SvROK($arg)) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = INT2PTR($type,tmp);
- }
- else
- croak(\"$var is not a reference\")
-
-T_SV_OBJ
- if (SvROK($arg)) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = INT2PTR($type,tmp);
- }
- else
- croak(\"$var is not a reference\")
-
-T_MG_OBJ
- if (SvROK($arg)) {
- IV tmp = SvIV((SV*)SvRV($arg));
- $var = INT2PTR($type,tmp);
- }
- else
- croak(\"$var is not a reference\")
-
-OUTPUT
-T_OP_OBJ
- sv_setiv(newSVrv($arg, cc_opclassname(aTHX_ (OP*)$var)), PTR2IV($var));
-
-T_SV_OBJ
- make_sv_object(aTHX_ ($arg), (SV*)($var));
-
-
-T_MG_OBJ
- sv_setiv(newSVrv($arg, "B::MAGIC"), PTR2IV($var));
OpenPOWER on IntegriCloud