/home/fresvfqn/firedamagerestorationcleanupbabylon.com/wp-content+WC/plugins/astra-sites/2022/B.tar
Concise.pm000064400000166034151002542700006473 0ustar00package B::Concise;
# Copyright (C) 2000-2003 Stephen McCamant. All rights reserved.
# This program is free software; you can redistribute and/or modify it
# under the same terms as Perl itself.

# Note: we need to keep track of how many use declarations/BEGIN
# blocks this module uses, so we can avoid printing them when user
# asks for the BEGIN blocks in her program. Update the comments and
# the count in concise_specials if you add or delete one. The
# -MO=Concise counts as use #1.

use strict; # use #2
use warnings; # uses #3 and #4, since warnings uses Carp

use Exporter (); # use #5

our $VERSION   = "0.999";
our @ISA       = qw(Exporter);
our @EXPORT_OK = qw( set_style set_style_standard add_callback
		     concise_subref concise_cv concise_main
		     add_style walk_output compile reset_sequence );
our %EXPORT_TAGS =
    ( io	=> [qw( walk_output compile reset_sequence )],
      style	=> [qw( add_style set_style_standard )],
      cb	=> [qw( add_callback )],
      mech	=> [qw( concise_subref concise_cv concise_main )],  );

# use #6
use B qw(class ppname main_start main_root main_cv cstring svref_2object
	 SVf_IOK SVf_NOK SVf_POK SVf_IVisUV SVf_FAKE OPf_KIDS OPf_SPECIAL
         OPf_STACKED
         OPpSPLIT_ASSIGN OPpSPLIT_LEX
	 CVf_ANON PAD_FAKELEX_ANON PAD_FAKELEX_MULTI SVf_ROK);

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)?)(?(:#hints)?)(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\t(?(op_other\t#otheraddr\n\t)?)"
    . "op_sibling\t#sibaddr\n\t"
    . "op_ppaddr\tPL_ppaddr[OP_#NAME]\n\top_type\t\t#typenum\n"
    . "\top_flags\t#flagval\n\top_private\t#privval\t#hintsval\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}],
  );

# Renderings, ie how Concise prints, is controlled by these vars
# primary:
our $stylename;		# selects current style from %style
my $order = "basic";	# how optree is walked & printed: basic, exec, tree

# rendering mechanics:
# these 'formats' are the line-rendering templates
# they're updated from %style when $stylename changes
my ($format, $gotofmt, $treefmt);

# lesser players:
my $base = 36;		# how <sequence#> is displayed
my $big_endian = 1;	# more <sequence#> display
my $tree_style = 0;	# tree-order details
my $banner = 1;		# print banner before optree is traversed
my $do_main = 0;	# force printing of main routine
my $show_src;		# show source code

# another factor: can affect all styles!
our @callbacks;		# allow external management

set_style_standard("concise");

my $curcv;
my $cop_seq_base;

sub set_style {
    ($format, $gotofmt, $treefmt) = @_;
    #warn "set_style: deprecated, use set_style_standard instead\n"; # someday
    die "expecting 3 style-format args\n" unless @_ == 3;
}

sub add_style {
    my ($newstyle,@args) = @_;
    die "style '$newstyle' already exists, choose a new name\n"
	if exists $style{$newstyle};
    die "expecting 3 style-format args\n" unless @args == 3;
    $style{$newstyle} = [@args];
    $stylename = $newstyle; # update rendering state
}

sub set_style_standard {
    ($stylename) = @_; # update rendering state
    die "err: style '$stylename' unknown\n" unless exists $style{$stylename};
    set_style(@{$style{$stylename}});
}

sub add_callback {
    push @callbacks, @_;
}

# output handle, used with all Concise-output printing
our $walkHandle;	# public for your convenience
BEGIN { $walkHandle = \*STDOUT }

sub walk_output { # updates $walkHandle
    my $handle = shift;
    return $walkHandle unless $handle; # allow use as accessor

    if (ref $handle eq 'SCALAR') {
	require Config;
	die "no perlio in this build, can't call walk_output (\\\$scalar)\n"
	    unless $Config::Config{useperlio};
	# in 5.8+, open(FILEHANDLE,MODE,REFERENCE) writes to string
	open my $tmp, '>', $handle;	# but cant re-set existing STDOUT
	$walkHandle = $tmp;		# so use my $tmp as intermediate var
	return $walkHandle;
    }
    my $iotype = ref $handle;
    die "expecting argument/object that can print\n"
	unless $iotype eq 'GLOB' or $iotype and $handle->can('print');
    $walkHandle = $handle;
}

sub concise_subref {
    my($order, $coderef, $name) = @_;
    my $codeobj = svref_2object($coderef);

    return concise_stashref(@_)
	unless ref($codeobj) =~ '^B::(?:CV|FM)\z';
    concise_cv_obj($order, $codeobj, $name);
}

sub concise_stashref {
    my($order, $h) = @_;
    local *s;
    foreach my $k (sort keys %$h) {
	next unless defined $h->{$k};
	*s = $h->{$k};
	my $coderef = *s{CODE} or next;
	reset_sequence();
	print "FUNC: ", *s, "\n";
	my $codeobj = svref_2object($coderef);
	next unless ref $codeobj eq 'B::CV';
	eval { concise_cv_obj($order, $codeobj, $k) };
	warn "err $@ on $codeobj" if $@;
    }
}

# This should have been called concise_subref, but it was exported
# under this name in versions before 0.56
*concise_cv = \&concise_subref;

sub concise_cv_obj {
    my ($order, $cv, $name) = @_;
    # name is either a string, or a CODE ref (copy of $cv arg??)

    $curcv = $cv;

    if (ref($cv->XSUBANY) =~ /B::(\w+)/) {
	print $walkHandle "$name is a constant sub, optimized to a $1\n";
	return;
    }
    if ($cv->XSUB) {
	print $walkHandle "$name is XS code\n";
	return;
    }
    if (class($cv->START) eq "NULL") {
	no strict 'refs';
	if (ref $name eq 'CODE') {
	    print $walkHandle "coderef $name has no START\n";
	}
	elsif (exists &$name) {
	    print $walkHandle "$name exists in stash, but has no START\n";
	}
	else {
	    print $walkHandle "$name not in symbol table\n";
	}
	return;
    }
    sequence($cv->START);
    if ($order eq "exec") {
	walk_exec($cv->START);
    }
    elsif ($order eq "basic") {
	# walk_topdown($cv->ROOT, sub { $_[0]->concise($_[1]) }, 0);
	my $root = $cv->ROOT;
	unless (ref $root eq 'B::NULL') {
	    walk_topdown($root, sub { $_[0]->concise($_[1]) }, 0);
	} else {
	    print $walkHandle "B::NULL encountered doing ROOT on $cv. avoiding disaster\n";
	}
    } else {
	print $walkHandle tree($cv->ROOT, 0);
    }
}

sub concise_main {
    my($order) = @_;
    sequence(main_start);
    $curcv = main_cv;
    if ($order eq "exec") {
	return if class(main_start) eq "NULL";
	walk_exec(main_start);
    } elsif ($order eq "tree") {
	return if class(main_root) eq "NULL";
	print $walkHandle tree(main_root, 0);
    } elsif ($order eq "basic") {
	return if class(main_root) eq "NULL";
	walk_topdown(main_root,
		     sub { $_[0]->concise($_[1]) }, 0);
    }
}

sub concise_specials {
    my($name, $order, @cv_s) = @_;
    my $i = 1;
    if ($name eq "BEGIN") {
	splice(@cv_s, 0, 8); # skip 7 BEGIN blocks in this file. NOW 8 ??
    } elsif ($name eq "CHECK") {
	pop @cv_s; # skip the CHECK block that calls us
    }
    for my $cv (@cv_s) {
	print $walkHandle "$name $i:\n";
	$i++;
	concise_cv_obj($order, $cv, $name);
    }
}

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 @render_packs; # collect -stash=<packages>

sub compileOpts {
    # set rendering state from options and args
    my (@options,@args);
    if (@_) {
	@options = grep(/^-/, @_);
	@args = grep(!/^-/, @_);
    }
    for my $o (@options) {
	# mode/order
	if ($o eq "-basic") {
	    $order = "basic";
	} elsif ($o eq "-exec") {
	    $order = "exec";
	} elsif ($o eq "-tree") {
	    $order = "tree";
	}
	# tree-specific
	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;
	}
	# sequence numbering
	elsif ($o =~ /^-base(\d+)$/) {
	    $base = $1;
	} elsif ($o eq "-bigendian") {
	    $big_endian = 1;
	} elsif ($o eq "-littleendian") {
	    $big_endian = 0;
	}
	# miscellaneous, presentation
	elsif ($o eq "-nobanner") {
	    $banner = 0;
	} elsif ($o eq "-banner") {
	    $banner = 1;
	}
	elsif ($o eq "-main") {
	    $do_main = 1;
	} elsif ($o eq "-nomain") {
	    $do_main = 0;
	} elsif ($o eq "-src") {
	    $show_src = 1;
	}
	elsif ($o =~ /^-stash=(.*)/) {
	    my $pkg = $1;
	    no strict 'refs';
	    if (! %{$pkg.'::'}) {
		eval "require $pkg";
	    } else {
		require Config;
		if (!$Config::Config{usedl}
		    && keys %{$pkg.'::'} == 1
		    && $pkg->can('bootstrap')) {
		    # It is something that we're statically linked to, but hasn't
		    # yet been used.
		    eval "require $pkg";
		}
	    }
	    push @render_packs, $pkg;
	}
	# line-style options
	elsif (exists $style{substr($o, 1)}) {
	    $stylename = substr($o, 1);
	    set_style_standard($stylename);
	} else {
	    warn "Option $o unrecognized";
	}
    }
    return (@args);
}

sub compile {
    my (@args) = compileOpts(@_);
    return sub {
	my @newargs = compileOpts(@_); # accept new rendering options
	warn "disregarding non-options: @newargs\n" if @newargs;

	for my $objname (@args) {
	    next unless $objname; # skip null args to avoid noisy responses

	    if ($objname eq "BEGIN") {
		concise_specials("BEGIN", $order,
				 B::begin_av->isa("B::AV") ?
				 B::begin_av->ARRAY : ());
	    } elsif ($objname eq "INIT") {
		concise_specials("INIT", $order,
				 B::init_av->isa("B::AV") ?
				 B::init_av->ARRAY : ());
	    } elsif ($objname eq "CHECK") {
		concise_specials("CHECK", $order,
				 B::check_av->isa("B::AV") ?
				 B::check_av->ARRAY : ());
	    } elsif ($objname eq "UNITCHECK") {
		concise_specials("UNITCHECK", $order,
				 B::unitcheck_av->isa("B::AV") ?
				 B::unitcheck_av->ARRAY : ());
	    } elsif ($objname eq "END") {
		concise_specials("END", $order,
				 B::end_av->isa("B::AV") ?
				 B::end_av->ARRAY : ());
	    }
	    else {
		# convert function names to subrefs
		if (ref $objname) {
		    print $walkHandle "B::Concise::compile($objname)\n"
			if $banner;
		    concise_subref($order, ($objname)x2);
		    next;
		} else {
		    $objname = "main::" . $objname unless $objname =~ /::/;
		    no strict 'refs';
		    my $glob = \*$objname;
		    unless (*$glob{CODE} || *$glob{FORMAT}) {
			print $walkHandle "$objname:\n" if $banner;
			print $walkHandle "err: unknown function ($objname)\n";
			return;
		    }
		    if (my $objref = *$glob{CODE}) {
			print $walkHandle "$objname:\n" if $banner;
			concise_subref($order, $objref, $objname);
		    }
		    if (my $objref = *$glob{FORMAT}) {
			print $walkHandle "$objname (FORMAT):\n"
			    if $banner;
			concise_subref($order, $objref, $objname);
		    }
		}
	    }
	}
	for my $pkg (@render_packs) {
	    no strict 'refs';
	    concise_stashref($order, \%{$pkg.'::'});
	}

	if (!@args or $do_main or @render_packs) {
	    print $walkHandle "main program:\n" if $do_main;
	    concise_main($order);
	}
	return @args;	# something
    }
}

my %labels;
my $lastnext;	# remembers op-chain, used to insert gotos

my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
	       'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
	       'PVOP' => '"', 'LOOP' => "{", 'COP' => ";", 'PADOP' => "#",
	       'METHOP' => '.', UNOP_AUX => '+');

no warnings 'qw'; # "Possible attempt to put comments..."; use #7
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> // /= CO';

my $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

sub op_flags { # common flags (see BASOP.op_flags in op.h)
    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;
}

my %sequence_num;
my $seq_max = 1;

sub reset_sequence {
    # reset the sequence
    %sequence_num = ();
    $seq_max = 1;
    $lastnext = 0;
}

sub seq {
    my($op) = @_;
    return "-" if not exists $sequence_num{$$op};
    return base_n($sequence_num{$$op});
}

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") {
	my $maybe_root = $op->code_list;
	if ( ref($maybe_root) and $maybe_root->isa("B::OP")
	 and not $op->flags & OPf_KIDS) {
	    walk_topdown($maybe_root, $sub, $level + 1);
	}
	$maybe_root = $op->pmreplroot;
	if (ref($maybe_root) and $maybe_root->isa("B::OP")) {
	    # It really is the root of the replacement, not something
	    # else stored here for lack of space elsewhere
	    walk_topdown($maybe_root, $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 (class($op) eq "LOGOP") {
		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}} = "NEXT";
		$labels{${$op->lastop}} = "LAST";
		$labels{${$op->redoop}} = "REDO";
	    }
	}
    }
    walklines(\@lines, 0);
}

# The structure of this routine is purposely modeled after op.c's peep()
sub sequence {
    my($op) = @_;
    my $oldop = 0;
    return if class($op) eq "NULL" or exists $sequence_num{$$op};
    for (; $$op; $op = $op->next) {
	last if exists $sequence_num{$$op};
	my $name = $op->name;
	$sequence_num{$$op} = $seq_max++;
	if (class($op) eq "LOGOP") {
	    sequence($op->other);
	} elsif (class($op) eq "LOOP") {
	    sequence($op->redoop);
	    sequence( $op->nextop);
	    sequence($op->lastop);
	} elsif ($name eq "subst" and $ {$op->pmreplstart}) {
	    sequence($op->pmreplstart);
	}
	$oldop = $op;
    }
}

sub fmt_line {    # generate text-line for op.
    my($hr, $op, $text, $level) = @_;

    $_->($hr, $op, \$text, \$level, $stylename) for @callbacks;

    return '' if $hr->{SKIP};	# suppress line if a callback said so
    return '' if $hr->{goto} and $hr->{goto} eq '-';	# no goto nowhere

    # spec: (?(text1#varText2)?)
    $text =~ s/\(\?\(([^\#]*?)\#(\w+)([^\#]*?)\)\?\)/
	$hr->{$2} ? $1.$hr->{$2}.$3 : ""/eg;

    # spec: (x(exec_text;basic_text)x)
    $text =~ s/\(x\((.*?);(.*?)\)x\)/$order eq "exec" ? $1 : $2/egs;

    # spec: (*(text)*)
    $text =~ s/\(\*\(([^;]*?)\)\*\)/$1 x $level/egs;

    # spec: (*(text1;text2)*)
    $text =~ s/\(\*\((.*?);(.*?)\)\*\)/$1 x ($level - 1) . $2 x ($level>0)/egs;

    # convert #Var to tag=>val form: Var\t#var
    $text =~ s/\#([A-Z][a-z]+)(\d+)?/\t\u$1\t\L#$1$2/gs;

    # spec: #varN
    $text =~ s/\#([a-zA-Z]+)(\d+)/sprintf("%-$2s", $hr->{$1})/eg;

    $text =~ s/\#([a-zA-Z]+)/$hr->{$1}/eg;	# populate #var's
    $text =~ s/[ \t]*~+[ \t]*/ /g;		# squeeze tildes

    $text = "# $hr->{src}\n$text" if $show_src and $hr->{src};

    chomp $text;
    return "$text\n" if $text ne "" and $order ne "tree";
    return $text; # suppress empty lines
}



# use require rather than use here to avoid disturbing tests that dump
# BEGIN blocks
require B::Op_private;



our %hints; # used to display each COP's op_hints values

# strict refs, subs, vars
@hints{0x2,0x200,0x400,0x20,0x40,0x80} = ('$', '&', '*', 'x$', 'x&', 'x*');
# integers, locale, bytes
@hints{0x1,0x4,0x8,0x10} = ('i', 'l', 'b');
# block scope, localise %^H, $^OPEN (in), $^OPEN (out)
@hints{0x100,0x20000,0x40000,0x80000} = ('{','%','<','>');
# overload new integer, float, binary, string, re
@hints{0x1000,0x2000,0x4000,0x8000,0x10000} = ('I', 'F', 'B', 'S', 'R');
# taint and eval
@hints{0x100000,0x200000} = ('T', 'E');
# filetest access, use utf8, unicode_strings feature
@hints{0x400000,0x800000,0x800} = ('X', 'U', 'us');

# pick up the feature hints constants.
# Note that we're relying on non-API parts of feature.pm,
# but its less naughty than just blindly copying those constants into
# this src file.
#
require feature;

sub hints_flags {
    my($x) = @_;
    my @s;
    for my $flag (sort {$b <=> $a} keys %hints) {
	if ($hints{$flag} and $x & $flag and $x >= $flag) {
	    $x -= $flag;
	    push @s, $hints{$flag};
	}
    }
    if ($x & $feature::hint_mask) {
        push @s, "fea=" . (($x & $feature::hint_mask) >> $feature::hint_shift);
        $x &= ~$feature::hint_mask;
    }
    push @s, sprintf "0x%x", $x if $x;
    return join(",", @s);
}


# return a string like 'LVINTRO,1' for the op $name with op_private
# value $x

sub private_flags {
    my($name, $x) = @_;
    my $entry = $B::Op_private::bits{$name};
    return $x ? "$x" : '' unless $entry;

    my @flags;
    my $bit;
    for ($bit = 7; $bit >= 0; $bit--) {
        next unless exists $entry->{$bit};
        my $e = $entry->{$bit};
        if (ref($e) eq 'HASH') {
            # bit field

            my ($bitmin, $bitmax, $bitmask, $enum, $label) =
                    @{$e}{qw(bitmin bitmax bitmask enum label)};
            $bit = $bitmin;
            next if defined $label && $label eq '-'; # display as raw number

            my $val = $x & $bitmask;
            $x &= ~$bitmask;
            $val >>= $bitmin;

            if (defined $enum) {
                # try to convert numeric $val into symbolic
                my @enum = @$enum;
                while (@enum) {
                    my $ix    = shift @enum;
                    my $name  = shift @enum;
                    my $label = shift @enum;
                    if ($val == $ix) {
                        $val = $label;
                        last;
                    }
                }
            }
            next if $val eq '0'; # don't display anonymous zero values
            push @flags, defined $label ? "$label=$val" : $val;

        }
        else {
            # flag bit
            my $label = $B::Op_private::labels{$e};
            next if defined $label && $label eq '-'; # display as raw number
            if ($x & (1<<$bit)) {
                $x -= (1<<$bit);
                push @flags, $label;
            }
        }
    }

    push @flags, $x if $x; # display unknown bits numerically
    return join ",", @flags;
}

sub concise_sv {
    my($sv, $hr, $preferpv) = @_;
    $hr->{svclass} = class($sv);
    $hr->{svclass} = "UV"
      if $hr->{svclass} eq "IV" and $sv->FLAGS & SVf_IVisUV;
    Carp::cluck("bad concise_sv: $sv") unless $sv and $$sv;
    $hr->{svaddr} = sprintf("%#x", $$sv);
    if ($hr->{svclass} eq "GV" && $sv->isGV_with_GP()) {
	my $gv = $sv;
	my $stash = $gv->STASH;
	if (class($stash) eq "SPECIAL") {
	    $stash = "<none>";
	}
	else {
	    $stash = $stash->NAME;
	}
	if ($stash eq "main") {
	    $stash = "";
	} else {
	    $stash = $stash . "::";
	}
	$hr->{svval} = "*$stash" . $gv->SAFENAME;
	return "*$stash" . $gv->SAFENAME;
    } else {
	if ($] >= 5.011) {
	    while (class($sv) eq "IV" && $sv->FLAGS & SVf_ROK) {
		$hr->{svval} .= "\\";
		$sv = $sv->RV;
	    }
	} else {
	    while (class($sv) eq "RV") {
		$hr->{svval} .= "\\";
		$sv = $sv->RV;
	    }
	}
	if (class($sv) eq "SPECIAL") {
	    $hr->{svval} .= ["Null", "sv_undef", "sv_yes", "sv_no"]->[$$sv];
	} elsif ($preferpv
	      && ($sv->FLAGS & SVf_POK || class($sv) eq "REGEXP")) {
	    $hr->{svval} .= cstring($sv->PV);
	} elsif ($sv->FLAGS & SVf_NOK) {
	    $hr->{svval} .= $sv->NV;
	} elsif ($sv->FLAGS & SVf_IOK) {
	    $hr->{svval} .= $sv->int_value;
	} elsif ($sv->FLAGS & SVf_POK || class($sv) eq "REGEXP") {
	    $hr->{svval} .= cstring($sv->PV);
	} elsif (class($sv) eq "HV") {
	    $hr->{svval} .= 'HASH';
	}

	$hr->{svval} = 'undef' unless defined $hr->{svval};
	my $out = $hr->{svclass};
	return $out .= " $hr->{svval}" ; 
    }
}

my %srclines;

sub fill_srclines {
    my $fullnm = shift;
    if ($fullnm eq '-e') {
	$srclines{$fullnm} = [ $fullnm, "-src not supported for -e" ];
	return;
    }
    open (my $fh, '<', $fullnm)
	or warn "# $fullnm: $!, (chdirs not supported by this feature yet)\n"
	and return;
    my @l = <$fh>;
    chomp @l;
    unshift @l, $fullnm; # like @{_<$fullnm} in debug, array starts at 1
    $srclines{$fullnm} = \@l;
}

# Given a pad target, return the pad var's name and cop range /
# fakeness, or failing that, its target number.
# e.g.
#   ('$i', '$i:5,7')
# or
#   ('$i', '$i:fake:a')
# or
#   ('t5', 't5')

sub padname {
    my ($targ) = @_;

    my ($targarg, $targarglife);
    my $padname = (($curcv->PADLIST->ARRAY)[0]->ARRAY)[$targ];
    if (defined $padname and class($padname) ne "SPECIAL" and
        $padname->LEN)
    {
        $targarg  = $padname->PVX;
        if ($padname->FLAGS & SVf_FAKE) {
            # These changes relate to the jumbo closure fix.
            # See changes 19939 and 20005
            my $fake = '';
            $fake .= 'a'
                if $padname->PARENT_FAKELEX_FLAGS & PAD_FAKELEX_ANON;
            $fake .= 'm'
                if $padname->PARENT_FAKELEX_FLAGS & PAD_FAKELEX_MULTI;
            $fake .= ':' . $padname->PARENT_PAD_INDEX
                if $curcv->CvFLAGS & CVf_ANON;
            $targarglife = "$targarg:FAKE:$fake";
        }
        else {
            my $intro = $padname->COP_SEQ_RANGE_LOW - $cop_seq_base;
            my $finish = int($padname->COP_SEQ_RANGE_HIGH) - $cop_seq_base;
            $finish = "end" if $finish == 999999999 - $cop_seq_base;
            $targarglife = "$targarg:$intro,$finish";
        }
    } else {
        $targarglife = $targarg = "t" . $targ;
    }
    return $targarg, $targarglife;
}



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};
    $h{privval} = $op->private;
    # for null ops, targ holds the old type
    my $origname = $h{name} eq "null" && $h{targ}
      ? substr(ppname($h{targ}), 3)
      : $h{name};
    $h{private} = private_flags($origname, $op->private);
    if ($op->folded) {
      $h{private} &&= "$h{private},";
      $h{private} .= "FOLD";
    }

    if ($h{name} ne $origname) { # a null op
	$h{exname} = "ex-$origname";
	$h{extarg} = "";
    } elsif ($h{private} =~ /\bREFC\b/) {
	# targ holds a reference count
        my $refs = "ref" . ($h{targ} != 1 ? "s" : "");
        $h{targarglife} = $h{targarg} = "$h{targ} $refs";
    } elsif ($h{targ}) {
	my $count = $h{name} eq 'padrange'
            ? ($op->private & $B::Op_private::defines{'OPpPADRANGE_COUNTMASK'})
            : 1;
	my (@targarg, @targarglife);
	for my $i (0..$count-1) {
	    my ($targarg, $targarglife) = padname($h{targ} + $i);
	    push @targarg,     $targarg;
	    push @targarglife, $targarglife;
	}
	$h{targarg}     = join '; ', @targarg;
	$h{targarglife} = join '; ', @targarglife;
    }

    $h{arg} = "";
    $h{svclass} = $h{svaddr} = $h{svval} = "";
    if ($h{class} eq "PMOP") {
	my $extra = '';
	my $precomp = $op->precomp;
	if (defined $precomp) {
	    $precomp = cstring($precomp); # Escape literal control sequences
 	    $precomp = "/$precomp/";
	} else {
	    $precomp = "";
	}
	if ($op->name eq 'subst') {
	    if (class($op->pmreplstart) ne "NULL") {
		undef $lastnext;
		$extra = " replstart->" . seq($op->pmreplstart);
	    }
	}
	elsif ($op->name eq 'split') {
            if (    ($op->private & OPpSPLIT_ASSIGN) # @array  = split
                 && (not $op->flags & OPf_STACKED))  # @{expr} = split
            {
                # with C<@array = split(/pat/, str);>,
                #  array is stored in /pat/'s pmreplroot; either
                # as an integer index into the pad (for a lexical array)
                # or as GV for a package array (which will be a pad index
                # on threaded builds)

                if ($op->private & $B::Op_private::defines{'OPpSPLIT_LEX'}) {
                    my $off = $op->pmreplroot; # union with op_pmtargetoff
                    my ($name, $full) = padname($off);
                    $extra = " => $full";
                }
                else {
                    # union with op_pmtargetoff, op_pmtargetgv
                    my $gv = $op->pmreplroot;
                    if (!ref($gv)) {
                        # the value is actually a pad offset
                        $gv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$gv]->NAME;
                    }
                    else {
                        # unthreaded: its a GV
                        $gv = $gv->NAME;
                    }
                    $extra = " => \@$gv";
                }
            }
	}
	$h{arg} = "($precomp$extra)";
    } elsif ($h{class} eq "PVOP" and $h{name} !~ '^transr?\z') {
	$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;
	my $pathnm = $loc;
	$loc =~ s[.*/][];
	my $ln = $op->line;
	$loc .= ":$ln";
	my($stash, $cseq) = ($op->stash->NAME, $op->cop_seq - $cop_seq_base);
	$h{arg} = "($label$stash $cseq $loc)";
	if ($show_src) {
	    fill_srclines($pathnm) unless exists $srclines{$pathnm};
	    # Would love to retain Jim's use of // but this code needs to be
	    # portable to 5.8.x
	    my $line = $srclines{$pathnm}[$ln];
	    $line = "-src unavailable under -e" unless defined $line;
	    $h{src} = "$ln: $line";
	}
    } 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) . ")";
	$h{otheraddr} = sprintf("%#x", $ {$op->other});
        if ($h{name} eq "argdefelem") {
            # targ used for element index
            $h{targarglife} = $h{targarg} = "";
            $h{arg} .= "[" . $op->targ . "]";
        }
    }
    elsif ($h{class} eq "SVOP" or $h{class} eq "PADOP") {
	unless ($h{name} eq 'aelemfast' and $op->flags & OPf_SPECIAL) {
	    my $idx = ($h{class} eq "SVOP") ? $op->targ : $op->padix;
	    if ($h{class} eq "PADOP" or !${$op->sv}) {
		my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$idx];
		$h{arg} = "[" . concise_sv($sv, \%h, 0) . "]";
		$h{targarglife} = $h{targarg} = "";
	    } else {
		$h{arg} = "(" . concise_sv($op->sv, \%h, 0) . ")";
	    }
	}
    }
    elsif ($h{class} eq "METHOP") {
        my $prefix = '';
        if ($h{name} eq 'method_redir' or $h{name} eq 'method_redir_super') {
            my $rclass_sv = $op->rclass;
            $rclass_sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$rclass_sv]
                unless ref $rclass_sv;
            $prefix .= 'PACKAGE "'.$rclass_sv->PV.'", ';
        }
        if ($h{name} ne "method") {
            if (${$op->meth_sv}) {
                $h{arg} = "($prefix" . concise_sv($op->meth_sv, \%h, 1) . ")";
            } else {
                my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
                $h{arg} = "[$prefix" . concise_sv($sv, \%h, 1) . "]";
                $h{targarglife} = $h{targarg} = "";
            }
        }
    }
    elsif ($h{class} eq "UNOP_AUX") {
        $h{arg} = "(" . $op->string($curcv) . ")";
    }

    $h{seq} = $h{hyphseq} = seq($op);
    $h{seq} = "" if $h{seq} eq "-";
    $h{opt} = $op->opt;
    $h{label} = $labels{$$op};
    $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);
    if ($op->can("hints")) {
      $h{hintsval} = $op->hints;
      $h{hints} = hints_flags($h{hintsval});
    } else {
      $h{hintsval} = $h{hints} = '';
    }
    $h{addr} = sprintf("%#x", $$op);
    $h{typenum} = $op->type;
    $h{noise} = $linenoise[$op->type];

    return fmt_line(\%h, $op, $format, $level);
}

sub B::OP::concise {
    my($op, $level) = @_;
    if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
	# insert a 'goto' line
	my $synth = {"seq" => seq($lastnext), "class" => class($lastnext),
		     "addr" => sprintf("%#x", $$lastnext),
		     "goto" => seq($lastnext), # simplify goto '-' removal
	     };
	print $walkHandle fmt_line($synth, $op, $gotofmt, $level+1);
    }
    $lastnext = $op->next;
    print $walkHandle concise_op($op, $level, $format);
}

# B::OP::terse (see Terse.pm) now just calls this
sub b_terse {
    my($op, $level) = @_;

    # This isn't necessarily right, but there's no easy way to get
    # from an OP to the right CV. This is a limitation of the
    # ->terse() interface style, and there isn't much to do about
    # it. In particular, we can die in concise_op if the main pad
    # isn't long enough, or has the wrong kind of entries, compared to
    # the pad a sub was compiled with. The fix for that would be to
    # make a backwards compatible "terse" format that never even
    # looked at the pad, just like the old B::Terse. I don't think
    # that's worth the effort, though.
    $curcv = main_cv unless $curcv;

    if ($order eq "exec" and $lastnext and $$lastnext != $$op) {
	# insert a 'goto'
	my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
		 "addr" => sprintf("%#x", $$lastnext)};
	print # $walkHandle
	    fmt_line($h, $op, $style{"terse"}[1], $level+1);
    }
    $lastnext = $op->next;
    print # $walkHandle 
	concise_op($op, $level, $style{"terse"}[0]);
}

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));
}

# *** Warning: fragile kludge ahead ***
# Because the B::* modules run in the same interpreter as the code
# they're compiling, their presence tends to distort the view we have of
# the code we're looking at. In particular, perl gives sequence numbers
# to COPs. If the program we're looking at were run on its own, this
# would start at 1. Because all of B::Concise and all the modules it
# uses are compiled first, though, by the time we get to the user's
# program the sequence number is already pretty high, which could be
# distracting if you're trying to tell OPs apart. Therefore we'd like to
# subtract an offset from all the sequence numbers we display, to
# restore the simpler view of the world. The trick is to know what that
# offset will be, when we're still compiling B::Concise!  If we
# hardcoded a value, it would have to change every time B::Concise or
# other modules we use do. To help a little, what we do here is compile
# a little code at the end of the module, and compute the base sequence
# number for the user's program as being a small offset later, so all we
# have to worry about are changes in the offset.

# [For 5.8.x and earlier perl is generating sequence numbers for all ops,
#  and using them to reference labels]


# When you say "perl -MO=Concise -e '$a'", the output should look like:

# 4  <@> leave[t1] vKP/REFC ->(end)
# 1     <0> enter ->2
 #^ smallest OP sequence number should be 1
# 2     <;> nextstate(main 1 -e:1) v ->3
 #                         ^ smallest COP sequence number should be 1
# -     <1> ex-rv2sv vK/1 ->4
# 3        <$> gvsv(*a) s ->4

# If the second of the marked numbers there isn't 1, it means you need
# to update the corresponding magic number in the next line.
# Remember, this needs to stay the last things in the module.

my $cop_seq_mnum = 16;
$cop_seq_base = svref_2object(eval 'sub{0;}')->START->cop_seq + $cop_seq_mnum;

1;

__END__

=head1 NAME

B::Concise - Walk Perl syntax tree, printing concise info about ops

=head1 SYNOPSIS

    perl -MO=Concise[,OPTIONS] foo.pl

    use B::Concise qw(set_style add_callback);

=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 displayed 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 EXAMPLE

Here's two outputs (or 'renderings'), using the -exec and -basic
(i.e. default) formatting conventions on the same code snippet.

    % perl -MO=Concise,-exec -e '$a = $b + 42'
    1  <0> enter
    2  <;> nextstate(main 1 -e:1) v
    3  <#> gvsv[*b] s
    4  <$> const[IV 42] s
 *  5  <2> add[t3] sK/2
    6  <#> gvsv[*a] s
    7  <2> sassign vKS/2
    8  <@> leave[1 ref] vKP/REFC

In this -exec rendering, each opcode is executed in the order shown.
The add opcode, marked with '*', is discussed in more detail.

The 1st column is the op's sequence number, starting at 1, and is
displayed in base 36 by default.  Here they're purely linear; the
sequences are very helpful when looking at code with loops and
branches.

The symbol between angle brackets indicates the op's type, for
example; <2> is a BINOP, <@> a LISTOP, and <#> is a PADOP, which is
used in threaded perls. (see L</"OP class abbreviations">).

The opname, as in B<'add[t1]'>, may be followed by op-specific
information in parentheses or brackets (ex B<'[t1]'>).

The op-flags (ex B<'sK/2'>) are described in (L</"OP flags
abbreviations">).

    % perl -MO=Concise -e '$a = $b + 42'
    8  <@> leave[1 ref] vKP/REFC ->(end)
    1     <0> enter ->2
    2     <;> nextstate(main 1 -e:1) v ->3
    7     <2> sassign vKS/2 ->8
 *  5        <2> add[t1] sK/2 ->6
    -           <1> ex-rv2sv sK/1 ->4
    3              <$> gvsv(*b) s ->4
    4           <$> const(IV 42) s ->5
    -        <1> ex-rv2sv sKRM*/1 ->7
    6           <$> gvsv(*a) s ->7

The default rendering is top-down, so they're not in execution order.
This form reflects the way the stack is used to parse and evaluate
expressions; the add operates on the two terms below it in the tree.

Nullops appear as C<ex-opname>, where I<opname> is an op that has been
optimized away by perl.  They're displayed with a sequence-number of
'-', because they are not executed (they don't appear in previous
example), they're printed here because they reflect the parse.

The arrow points to the sequence number of the next op; they're not
displayed in -exec mode, for obvious reasons.

Note that because this rendering was done on a non-threaded perl, the
PADOPs in the previous examples are now SVOPs, and some (but not all)
of the square brackets have been replaced by round ones.  This is a
subtle feature to provide some visual distinction between renderings
on threaded and un-threaded perls.


=head1 OPTIONS

Arguments that don't start with a hyphen are taken to be the names of
subroutines or formats to render; 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 rendered.  Passing C<BEGIN>, C<UNITCHECK>,
C<CHECK>, C<INIT>, or C<END> will cause all of the corresponding
special blocks to be printed.  Arguments must follow options.

Options affect how things are rendered (ie printed).  They're presented
here by their visual effect, 1st being strongest.  They're grouped
according to how they interrelate; within each group the options are
mutually exclusive (unless otherwise stated).

=head2 Options for Opcode Ordering

These options control the 'vertical display' of opcodes.  The display
'order' is also called 'mode' elsewhere in this document.

=over 4

=item B<-basic>

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, and the '->' at the end of the line indicates the
next opcode in execution order.  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).

=back

=head2 Options for Line-Style

These options select the line-style (or just style) used to render
each opcode, and dictates what info is actually printed into each line.

=over 4

=item B<-concise>

Use the author's favorite set of formatting conventions. This is the
default, of course.

=item B<-terse>

Use formatting conventions that emulate the output of B<B::Terse>. The
basic mode is almost indistinguishable from the real B<B::Terse>, and the
exec mode looks very similar, but is in a more logical order and lacks
curly brackets. B<B::Terse> doesn't have a tree mode, so the tree mode
is only vaguely reminiscent of B<B::Terse>.

=item B<-linenoise>

Use formatting conventions in which the name of each OP, rather than being
written out in full, is represented by a one- or two-character abbreviation.
This is mainly a joke.

=item B<-debug>

Use formatting conventions reminiscent of B<B::Debug>; these aren't
very concise at all.

=item B<-env>

Use formatting conventions read from the environment variables
C<B_CONCISE_FORMAT>, C<B_CONCISE_GOTO_FORMAT>, and C<B_CONCISE_TREE_FORMAT>.

=back

=head2 Options for tree-specific formatting

=over 4

=item B<-compact>

Use a tree format in which the minimum amount of space is used for the
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.

=back

These are pairwise exclusive, i.e. compact or loose, vt or ascii.

=head2 Options controlling sequence numbering

=over 4

=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 sequence numbers with the least significant digit first.  This is
obviously mutually exclusive with bigendian.

=back

=head2 Other options

=over 4

=item B<-src>

With this option, the rendering of each statement (starting with the
nextstate OP) will be preceded by the 1st line of source code that
generates it.  For example:

    1  <0> enter
    # 1: my $i;
    2  <;> nextstate(main 1 junk.pl:1) v:{
    3  <0> padsv[$i:1,10] vM/LVINTRO
    # 3: for $i (0..9) {
    4  <;> nextstate(main 3 junk.pl:3) v:{
    5  <0> pushmark s
    6  <$> const[IV 0] s
    7  <$> const[IV 9] s
    8  <{> enteriter(next->j last->m redo->9)[$i:1,10] lKS
    k  <0> iter s
    l  <|> and(other->9) vK/1
    # 4:     print "line ";
    9      <;> nextstate(main 2 junk.pl:4) v
    a      <0> pushmark s
    b      <$> const[PV "line "] s
    c      <@> print vK
    # 5:     print "$i\n";
    ...

=item B<-stash="somepackage">

With this, "somepackage" will be required, then the stash is
inspected, and each function is rendered.

=back

The following options are pairwise exclusive.

=over 4

=item B<-main>

Include the main program in the output, even if subroutines were also
specified.  This rendering is normally suppressed when a subroutine
name or reference is given.

=item B<-nomain>

This restores the default behavior after you've changed it with '-main'
(it's not normally needed).  If no subroutine name/ref is given, main is
rendered, regardless of this flag.

=item B<-nobanner>

Renderings usually include a banner line identifying the function name
or stringified subref.  This suppresses the printing of the banner.

TBC: Remove the stringified coderef; while it provides a 'cookie' for
each function rendered, the cookies used should be 1,2,3.. not a
random hex-address.  It also complicates string comparison of two
different trees.

=item B<-banner>

restores default banner behavior.

=item B<-banneris> => subref

TBC: a hookpoint (and an option to set it) for a user-supplied
function to produce a banner appropriate for users needs.  It's not
ideal, because the rendering-state variables, which are a natural
candidate for use in concise.t, are unavailable to the user.

=back

=head2 Option Stickiness

If you invoke Concise more than once in a program, you should know that
the options are 'sticky'.  This means that the options you provide in
the first call will be remembered for the 2nd call, unless you
re-specify or change them.

=head1 ABBREVIATIONS

The concise style uses symbols to convey maximum info with minimal
clutter (like hex addresses).  With just a little practice, you can
start to see the flowers, not just the branches, in the trees.

=head2 OP class abbreviations

These symbols appear before the op-name, and indicate the
B:: namespace that represents the ops in your Perl code.

    0      OP (aka BASEOP)  An OP with no children
    1      UNOP             An OP with one child
    +      UNOP_AUX         A UNOP with auxillary fields
    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
    #      PADOP            An OP with a GV on the pad
    .      METHOP           An OP with method call info

=head2 OP flags abbreviations

OP flags are either public or private.  The public flags alter the
behavior of each opcode in consistent ways, and are represented by 0
or more single characters.

    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)
                            Want is unknown
    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)

Private flags, if any are set for an opcode, are displayed after a '/'

    8  <@> leave[1 ref] vKP/REFC ->(end)
    7     <2> sassign vKS/2 ->8

They're opcode specific, and occur less often than the public ones, so
they're represented by short mnemonics instead of single-chars; see
B::Op_private and F<regen/op_private> for more details.

=head1 FORMATTING SPECIFICATIONS

For each line-style ('concise', 'terse', 'linenoise', etc.) there are
3 format-specs which control how OPs are rendered.

The first is the 'default' format, which is used in both basic and exec
modes to print all opcodes.  The 2nd, goto-format, is used in exec
mode when branches are encountered.  They're not real opcodes, and are
inserted to look like a closing curly brace.  The tree-format is tree
specific.

When a line is rendered, the correct format-spec is copied and scanned
for the following items; data is substituted in, and other
manipulations like basic indenting are done, for each opcode rendered.

There are 3 kinds of items that may be populated; special patterns,
#vars, and literal text, which is copied verbatim.  (Yes, it's a set
of s///g steps.)

=head2 Special Patterns

These items are the primitives used to perform indenting, and to
select text from amongst alternatives.

=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<~>

Any number of tildes and surrounding whitespace will be collapsed to
a single space.

=back

=head2 # Variables

These #vars represent opcode properties that you may want as part of
your rendering.  The '#' is intended as a private sigil; a #var's
value is interpolated into the style-line, much like "read $this".

These vars take 3 forms:

=over 4

=item B<#>I<var>

A property named 'var' is assumed to exist for the opcodes, and is
interpolated into the rendering.

=item B<#>I<var>I<N>

Generates the value of I<var>, left justified to fill I<N> spaces.
Note that this means while you can have properties 'foo' and 'foo2',
you cannot render 'foo2', but you could with 'foo2a'.  You would be
wise not to rely on this behavior going forward ;-)

=item B<#>I<Var>

This ucfirst form of #var generates a tag-value form of itself for
display; it converts '#Var' into a 'Var => #var' style, which is then
handled as described above.  (Imp-note: #Vars cannot be used for
conditional-fills, because the => #var transform is done after the check
for #Var's value).

=back

The following variables are 'defined' by B::Concise; when they are
used in a style, their respective values are plugged into the
rendering of each opcode.

Only some of these are used by the standard styles, the others are
provided for you to delve into optree mechanics, should you wish to
add a new style (see L</add_style> below) that uses them.  You can
also add new ones using L</add_callback>.

=over 4

=item B<#addr>

The address of the OP, in hexadecimal.

=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 parentheses.

=item B<#class>

The B-determined class of the OP, in all caps.

=item B<#classsym>

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 hexadecimal.

=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<#hints>

The COP's hint flags, rendered with abbreviated names if possible. An empty
string if this is not a COP. Here are the symbols used:

    $ strict refs
    & strict subs
    * strict vars
   x$ explicit use/no strict refs
   x& explicit use/no strict subs
   x* explicit use/no strict vars
    i integers
    l locale
    b bytes
    { block scope
    % localise %^H
    < open in
    > open out
    I overload int
    F overload float
    B overload binary
    S overload string
    R overload re
    T taint
    E eval
    X filetest access
    U utf-8

    us      use feature 'unicode_strings'
    fea=NNN feature bundle number

=item B<#hintsval>

The numeric value of the COP's hint flags, or an empty string if this is not
a COP.

=item B<#hyphseq>

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 hexadecimal.

=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 hexadecimal.

=item B<#noise>

A one- or 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. Note that this is a sequence number
generated by B::Concise.

=item B<#seqnum>

5.8.x and earlier only. 5.9 and later do not provide this.

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<#opt>

Whether or not the op has been optimized by the peephole optimizer.

Only available in 5.9 and later.

=item B<#sibaddr>

The address of the OP's next youngest sibling, in hexadecimal.

=item B<#svaddr>

The address of the OP's SV, if it has an SV, in hexadecimal.

=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 One-Liner Command tips

=over 4

=item perl -MO=Concise,bar foo.pl

Renders only bar() from foo.pl.  To see main, drop the ',bar'.  To see
both, add ',-main'

=item perl -MDigest::MD5=md5 -MO=Concise,md5 -e1

Identifies md5 as an XS function.  The export is needed so that BC can
find it in main.

=item perl -MPOSIX -MO=Concise,_POSIX_ARG_MAX -e1

Identifies _POSIX_ARG_MAX as a constant sub, optimized to an IV.
Although POSIX isn't entirely consistent across platforms, this is
likely to be present in virtually all of them.

=item perl -MPOSIX -MO=Concise,a -e 'print _POSIX_SAVED_IDS'

This renders a print statement, which includes a call to the function.
It's identical to rendering a file with a use call and that single
statement, except for the filename which appears in the nextstate ops.

=item perl -MPOSIX -MO=Concise,a -e 'sub a{_POSIX_SAVED_IDS}'

This is B<very> similar to previous, only the first two ops differ.  This
subroutine rendering is more representative, insofar as a single main
program will have many subs.

=item perl -MB::Concise -e 'B::Concise::compile("-exec","-src", \%B::Concise::)->()'

This renders all functions in the B::Concise package with the source
lines.  It eschews the O framework so that the stashref can be passed
directly to B::Concise::compile().  See -stash option for a more
convenient way to render a package.

=back

=head1 Using B::Concise outside of the O framework

The common (and original) usage of B::Concise was for command-line
renderings of simple code, as given in EXAMPLE.  But you can also use
B<B::Concise> from your code, and call compile() directly, and
repeatedly.  By doing so, you can avoid the compile-time only
operation of O.pm, and even use the debugger to step through
B::Concise::compile() itself.

Once you're doing this, you may alter Concise output by adding new
rendering styles, and by optionally adding callback routines which
populate new variables, if such were referenced from those (just
added) styles.  

=head2 Example: Altering Concise Renderings

    use B::Concise qw(set_style add_callback);
    add_style($yourStyleName => $defaultfmt, $gotofmt, $treefmt);
    add_callback
      ( sub {
            my ($h, $op, $format, $level, $stylename) = @_;
            $h->{variable} = some_func($op);
        });
    $walker = B::Concise::compile(@options,@subnames,@subrefs);
    $walker->();

=head2 set_style()

B<set_style> accepts 3 arguments, and updates the three format-specs
comprising a line-style (basic-exec, goto, tree).  It has one minor
drawback though; it doesn't register the style under a new name.  This
can become an issue if you render more than once and switch styles.
Thus you may prefer to use add_style() and/or set_style_standard()
instead.

=head2 set_style_standard($name)

This restores one of the standard line-styles: C<terse>, C<concise>,
C<linenoise>, C<debug>, C<env>, into effect.  It also accepts style
names previously defined with add_style().

=head2 add_style ()

This subroutine accepts a new style name and three style arguments as
above, and creates, registers, and selects the newly named style.  It is
an error to re-add a style; call set_style_standard() to switch between
several styles.

=head2 add_callback ()

If your newly minted styles refer to any new #variables, you'll need
to define a callback subroutine that will populate (or modify) those
variables.  They are then available for use in the style you've
chosen.

The callbacks are called for each opcode visited by Concise, in the
same order as they are added.  Each subroutine is passed five
parameters.

  1. A hashref, containing the variable names and values which are
     populated into the report-line for the op
  2. the op, as a B<B::OP> object
  3. a reference to the format string
  4. the formatting (indent) level
  5. the selected stylename

To define your own variables, simply add them to the hash, or change
existing values if you need to.  The level and format are passed in as
references to scalars, but it is unlikely that they will need to be
changed or even used.

=head2 Running B::Concise::compile()

B<compile> accepts options as described above in L</OPTIONS>, and
arguments, which are either coderefs, or subroutine names.

It constructs and returns a $treewalker coderef, which when invoked,
traverses, or walks, and renders the optrees of the given arguments to
STDOUT.  You can reuse this, and can change the rendering style used
each time; thereafter the coderef renders in the new style.

B<walk_output> lets you change the print destination from STDOUT to
another open filehandle, or into a string passed as a ref (unless
you've built perl with -Uuseperlio).

  my $walker = B::Concise::compile('-terse','aFuncName', \&aSubRef); # 1
  walk_output(\my $buf);
  $walker->();			        # 1 renders -terse
  set_style_standard('concise');	# 2
  $walker->();  		        # 2 renders -concise
  $walker->(@new);			# 3 renders whatever
  print "3 different renderings: terse, concise, and @new: $buf\n";

When $walker is called, it traverses the subroutines supplied when it
was created, and renders them using the current style.  You can change
the style afterwards in several different ways:

  1. call C<compile>, altering style or mode/order
  2. call C<set_style_standard>
  3. call $walker, passing @new options

Passing new options to the $walker is the easiest way to change
amongst any pre-defined styles (the ones you add are automatically
recognized as options), and is the only way to alter rendering order
without calling compile again.  Note however that rendering state is
still shared amongst multiple $walker objects, so they must still be
used in a coordinated manner.

=head2 B::Concise::reset_sequence()

This function (not exported) lets you reset the sequence numbers (note
that they're numbered arbitrarily, their goal being to be human
readable).  Its purpose is mostly to support testing, i.e. to compare
the concise output from two identical anonymous subroutines (but
different instances).  Without the reset, B::Concise, seeing that
they're separate optrees, generates different sequence numbers in
the output.

=head2 Errors

Errors in rendering (non-existent function-name, non-existent coderef)
are written to the STDOUT, or wherever you've set it via
walk_output().

Errors using the various *style* calls, and bad args to walk_output(),
result in die().  Use an eval if you wish to catch these errors and
continue processing.

=head1 AUTHOR

Stephen McCamant, E<lt>smcc@CSUA.Berkeley.EDUE<gt>.

=cut
Showlex.pm000064400000013030151002542700006524 0ustar00package B::Showlex;

our $VERSION = '1.05';

use strict;
use B qw(svref_2object comppadlist class);
use B::Terse ();
use B::Concise ();

#
# 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
#


# borrowed from B::Concise
our $walkHandle = \*STDOUT;

sub walk_output { # updates $walkHandle
    $walkHandle = B::Concise::walk_output(@_);
    #print "got $walkHandle";
    #print $walkHandle "using it";
    $walkHandle;
}

sub shownamearray {
    my ($name, $av) = @_;
    my @els = $av->ARRAY;
    my $count = @els;
    my $i;
    print $walkHandle "$name has $count entries\n";
    for ($i = 0; $i < $count; $i++) {
	my $sv = $els[$i];
	if (class($sv) ne "SPECIAL") {
	    printf $walkHandle "$i: (0x%lx) %s\n",
				$$sv, $sv->PVX // "undef" || "const";
	} else {
	    printf $walkHandle "$i: %s\n", $sv->terse;
	    #printf $walkHandle "$i: %s\n", B::Concise::concise_sv($sv);
	}
    }
}

sub showvaluearray {
    my ($name, $av) = @_;
    my @els = $av->ARRAY;
    my $count = @els;
    my $i;
    print $walkHandle "$name has $count entries\n";
    for ($i = 0; $i < $count; $i++) {
	printf $walkHandle "$i: %s\n", $els[$i]->terse;
	#print $walkHandle "$i: %s\n", B::Concise::concise_sv($els[$i]);
    }
}

sub showlex {
    my ($objname, $namesav, $valsav) = @_;
    shownamearray("Pad of lexical names for $objname", $namesav);
    showvaluearray("Pad of lexical values for $objname", $valsav);
}

my ($newlex, $nosp1); # rendering state vars

sub padname_terse {
    my $name = shift;
    return $name->terse if class($name) eq 'SPECIAL';
    my $str = $name->PVX;
    return sprintf "(0x%lx) %s",
	       $$name,
	       length $str ? qq'"$str"' : defined $str ? "const" : 'undef';
}

sub newlex { # drop-in for showlex
    my ($objname, $names, $vals) = @_;
    my @names = $names->ARRAY;
    my @vals  = $vals->ARRAY;
    my $count = @names;
    print $walkHandle "$objname Pad has $count entries\n";
    printf $walkHandle "0: %s\n", padname_terse($names[0]) unless $nosp1;
    for (my $i = 1; $i < $count; $i++) {
	printf $walkHandle "$i: %s = %s\n", padname_terse($names[$i]),
					    $vals[$i]->terse,
	    unless $nosp1
	       and class($names[$i]) eq 'SPECIAL' || !$names[$i]->LEN;
    }
}

sub showlex_obj {
    my ($objname, $obj) = @_;
    $objname =~ s/^&main::/&/;
    showlex($objname, svref_2object($obj)->PADLIST->ARRAY) if !$newlex;
    newlex ($objname, svref_2object($obj)->PADLIST->ARRAY) if  $newlex;
}

sub showlex_main {
    showlex("comppadlist", comppadlist->ARRAY)	if !$newlex;
    newlex ("main", comppadlist->ARRAY)		if  $newlex;
}

sub compile {
    my @options = grep(/^-/, @_);
    my @args = grep(!/^-/, @_);
    for my $o (@options) {
	$newlex = 1 if $o eq "-newlex";
	$nosp1  = 1 if $o eq "-nosp";
    }

    return \&showlex_main unless @args;
    return sub {
	my $objref;
	foreach my $objname (@args) {
	    next unless $objname;	# skip nulls w/o carping

	    if (ref $objname) {
		print $walkHandle "B::Showlex::compile($objname)\n";
		$objref = $objname;
	    } else {
		$objname = "main::$objname" unless $objname =~ /::/;
		print $walkHandle "$objname:\n";
		no strict 'refs';
		die "err: unknown function ($objname)\n"
		    unless *{$objname}{CODE};
		$objref = \&$objname;
	    }
	    showlex_obj($objname, $objref);
	}
    }
}

1;

__END__

=head1 NAME

B::Showlex - Show lexical variables used in functions or files

=head1 SYNOPSIS

	perl -MO=Showlex[,-OPTIONS][,SUBROUTINE] foo.pl

=head1 DESCRIPTION

When a comma-separated list of subroutine names is given as options, Showlex
prints the lexical variables used in those subroutines.  Otherwise, it prints
the file-scope lexicals in the file.

=head1 EXAMPLES

Traditional form:

 $ perl -MO=Showlex -e 'my ($i,$j,$k)=(1,"foo")'
 Pad of lexical names for comppadlist has 4 entries
 0: (0x8caea4) undef
 1: (0x9db0fb0) $i
 2: (0x9db0f38) $j
 3: (0x9db0f50) $k
 Pad of lexical values for comppadlist has 5 entries
 0: SPECIAL #1 &PL_sv_undef
 1: NULL (0x9da4234)
 2: NULL (0x9db0f2c)
 3: NULL (0x9db0f44)
 4: NULL (0x9da4264)
 -e syntax OK

New-style form:

 $ perl -MO=Showlex,-newlex -e 'my ($i,$j,$k)=(1,"foo")'
 main Pad has 4 entries
 0: (0x8caea4) undef
 1: (0xa0c4fb8) "$i" = NULL (0xa0b8234)
 2: (0xa0c4f40) "$j" = NULL (0xa0c4f34)
 3: (0xa0c4f58) "$k" = NULL (0xa0c4f4c)
 -e syntax OK

New form, no specials, outside O framework:

 $ perl -MB::Showlex -e \
    'my ($i,$j,$k)=(1,"foo"); B::Showlex::compile(-newlex,-nosp)->()'
 main Pad has 4 entries
 1: (0x998ffb0) "$i" = IV (0x9983234) 1
 2: (0x998ff68) "$j" = PV (0x998ff5c) "foo"
 3: (0x998ff80) "$k" = NULL (0x998ff74)

Note that this example shows the values of the lexicals, whereas the other
examples did not (as they're compile-time only).

=head2 OPTIONS

The C<-newlex> option produces a more readable C<< name => value >> format,
and is shown in the second example above.

The C<-nosp> option eliminates reporting of SPECIALs, such as C<0: SPECIAL
#1 &PL_sv_undef> above.  Reporting of SPECIALs can sometimes overwhelm
your declared lexicals.

=head1 SEE ALSO

L<B::Showlex> can also be used outside of the O framework, as in the third
example.  See L<B::Concise> for a fuller explanation of reasons.

=head1 TODO

Some of the reported info, such as hex addresses, is not particularly
valuable.  Other information would be more useful for the typical
programmer, such as line-numbers, pad-slot reuses, etc..  Given this,
-newlex is not a particularly good flag-name.

=head1 AUTHOR

Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>

=cut
Xref.pm000064400000030066151002542700006007 0ustar00package B::Xref;

our $VERSION = '1.06';

=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        line numbers
	  object2        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".

For instance, here's part of the report from the I<pod2man> program that
comes with Perl:

  Subroutine clear_noremap
    Package (lexical)
      $ready_to_print   i1069, 1079
    Package main
      $&                1086
      $.                1086
      $0                1086
      $1                1087
      $2                1085, 1085
      $3                1085, 1085
      $ARGV             1086
      %HTML_Escapes     1085, 1085

This shows the variables used in the subroutine C<clear_noremap>.  The
variable C<$ready_to_print> is a my() (lexical) variable,
B<i>ntroduced (first declared with my()) on line 1069, and used on
line 1079.  The variable C<$&> from the main package is used on 1086,
and so on.

A line number may be prefixed by a single letter:

=over 4

=item i

Lexical variable introduced (declared with my()) for the first time.

=item &

Subroutine or method call.

=item s

Subroutine defined.

=item r

Format defined.

=back

The most useful option the cross referencer has is to save the report
to a separate file.  For instance, to save the report on
I<myperlprogram> to the file I<report>:

  $ perl -MO=Xref,-oreport myperlprogram

=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>

Don't output the "(definitions)" sections.

=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 OPpOUR_INTRO cstring
        );

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) =~ '^(?:SPECIAL|NULL)\z';
    ($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";
            next if class($valsv->STASH) eq 'SPECIAL';
	    # 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_padrange {
    my $op = shift;
    my $count = $op->private & 127;
    for my $i (0..$count-1) {
	$top = $pad[$op->targ + $i];
	process($top, $op->private & OPpLVAL_INTRO ? "intro" : "used");
    }
}

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 ($op, $var, $as) = @_;
    $var->[1] = $as . $var->[1];
    process($var, $op->private & OPpOUR_INTRO ? "intro" : "used");
}

sub pp_rv2cv { deref(shift, $top, "&"); }
sub pp_rv2hv { deref(shift, $top, "%"); }
sub pp_rv2sv { deref(shift, $top, "\$"); }
sub pp_rv2av { deref(shift, $top, "\@"); }
sub pp_rv2gv { deref(shift, $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->SAFENAME];
    }
    process($top, $op->private & OPpLVAL_INTRO ||
                  $op->private & OPpOUR_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->SAFENAME];
    }
    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)
		? cstring($sv->PV) : "?"];
    }
    else {
	$top = $pad[$op->targ];
	$top = UNKNOWN unless $top;
    }
}

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 PerlIO::Layer
		      attributes utf8 warnings)) {
        $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;
Terse.pm000064400000006136151002542700006166 0ustar00package B::Terse;

our $VERSION = '1.07';

use strict;
use B qw(class @specialsv_name);
use B::Concise qw(concise_subref set_style_standard);
use Carp;

sub terse {
    my ($order, $subref) = @_;
    set_style_standard("terse");
    if ($order eq "exec") {
	concise_subref('exec', $subref);
    } else {
	concise_subref('basic', $subref);
    }
}

sub compile {
    my @args = @_;
    my $order = @args ? shift(@args) : "";
    $order = "-exec" if $order eq "exec";
    unshift @args, $order if $order ne "";
    B::Concise::compile("-terse", @args);
}

sub indent {
    my ($level) = @_ ? shift : 0;
    return "    " x $level;
}

# Don't use this, at least on OPs in subroutines: it has no way of
# getting to the pad, and will give wrong answers or crash.
sub B::OP::terse {
    carp "B::OP::terse is deprecated and will go away in Perl 5.28; use B::Concise instead";
    B::Concise::b_terse(@_);
}

sub B::SV::terse {
    my($sv, $level) = (@_, 0);
    my %info;
    B::Concise::concise_sv($sv, \%info);
    my $s = indent($level)
	. B::Concise::fmt_line(\%info, $sv,
				 "#svclass~(?((#svaddr))?)~#svval", 0);
    chomp $s;
    print "$s\n" unless defined wantarray;
    $s;
}

sub B::NULL::terse {
    my ($sv, $level) = (@_, 0);
    my $s = indent($level) . sprintf "%s (0x%lx)", class($sv), $$sv;
    print "$s\n" unless defined wantarray;
    $s;
}

sub B::SPECIAL::terse {
    my ($sv, $level) = (@_, 0);
    my $s = indent($level)
	. sprintf( "%s #%d %s", class($sv), $$sv, $specialsv_name[$$sv]);
    print "$s\n" unless defined wantarray;
    $s;
}

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

This module prints the contents of the parse tree, but without as much
information as L<B::Debug>.  For comparison, C<print "Hello, world.">
produced 96 lines of output from B::Debug, but only 6 from B::Terse.

This module is useful for people who are writing their own back end,
or who are learning about the Perl internals.  It's not useful to the
average programmer.

This version of B::Terse is really just a wrapper that calls L<B::Concise>
with the B<-terse> option. It is provided for compatibility with old scripts
(and habits) but using B::Concise directly is now recommended instead.

For compatibility with the old B::Terse, this module also adds a
method named C<terse> to B::OP and B::SV objects. The B::SV method is
largely compatible with the old one, though authors of new software
might be advised to choose a more user-friendly output format. The
B::OP C<terse> method, however, doesn't work well. Since B::Terse was
first written, much more information in OPs has migrated to the
scratchpad datastructure, but the C<terse> interface doesn't have any
way of getting to the correct pad. As a kludge, the new version will
always use the pad for the main program, but for OPs in subroutines
this will give the wrong answer or crash.

=head1 AUTHOR

The original version of B::Terse was written by Malcolm Beattie,
E<lt>mbeattie@sable.ox.ac.ukE<gt>. This wrapper was written by Stephen
McCamant, E<lt>smcc@MIT.EDUE<gt>.

=cut
B.so000075500000260750151003731440005303 0ustar00ELF>�P@�Z@8	@H#H# P$P$!P$!�+�+ �J�J!�J!888$$(#(#(#  S�td(#(#(#  P�td�����Q�tdR�tdP$P$!P$!�+�+GNUcH�Hb3ώPp*�Y�7��*ƈ^�@ ^`aBE���|�qX[
���y� �}0��n�)�0��ln��09��������G e��)Y�����#�y���[�� �KIHr�XW�=���O�, �>f�AVdF"y����+P!>P!2P!B0�o__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizelibpthread.so.0Perl_croak_xs_usagePerl_sv_newmortalPerl_newSVrvPerl_sv_setivPerl_gv_fetchpvn_flagsPerl_sv_2iv_flagsPerl_croak_nocontextPerl_sv_setuv_mgPerl_sv_setpvnPerl_stack_growPerl_mg_setPerl_sv_2mortalPerl_newSVhekPerl_newSVivPerl_newSVuvPerl_markstack_growPerl_sv_setiv_mgPerl_refcounted_he_chain_2hvPerl_newRV_noincPerl_newSVpvn_flagsPerl_hv_placeholders_getPerl_hv_iterinitPerl_hv_iternext_flagsPerl_hv_riter_pPerl_hv_fillPerl_cvgv_from_hekPerl_cv_const_svPerl_op_classPL_opargsPerl_mg_sizePerl_PerlIO_stderrPerl_PerlIO_stdoutPerl_sv_2pv_flagsPerl_PerlIO_stdinPerl_gv_fetchfilePerl_croakPerl_sv_setuvstrlenPerl_mg_findPerl_sv_2nv_flagsPerl_sv_setnv_mg__stack_chk_failPerl_newSVpvPerl_newSVnvPerl_newRVPerl_av_fetchPerl_newSVpvfPerl_newSVpvnPerl_multideref_stringifyPerl_sv_catpvfPerl_newSVPL_charclassPerl_sv_catpvn_flagsPerl_sv_uni_displaystrchrPL_op_namePerl_sv_setpvfstrcmpPerl_sv_2bool_flagsPerl_call_methodPerl_gv_stashpvPerl_sv_blessPerl_sv_backoffPerl_hv_common_key_lenPerl_newCONSTSUBPerl_sv_upgradePL_hash_seedPerl_sv_2pvbytePerl_get_svPerl_hv_commonPerl_emulate_cop_ioPerl_cop_fetch_labelPerl_op_parentPerl_sv_magicextPerl_sv_free2PL_op_descPerl_custom_op_get_fieldboot_BPerl_xs_handshakePerl_newXS_deffilePL_thr_keypthread_getspecificPerl_get_hvPerl_get_avPerl_av_pushPerl_mro_method_changed_inPerl_my_cxt_initPerl_newXSPerl_sv_setsv_flagsPerl_xs_boot_epiloglibperl.so.5.26libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.4U ui	C!ii
Oui	CP$!`QX$! Q`$!`$!�$!���$!���$!���$!���$!���$!��%!�(%!�@%!�X%!#�p%!,��%!5��%!?��%!I��%!V��%!f�&!v�&!��0&!��H&!��`&!��x&!���&!���&!��&!��&!��&!�'!�� '!�8'!�P'!�h'!)��'!5��'!>��'!G��'!O��'!V��'!]�(!g�((!n�@(!w�X(!��p(!���(!���(!���(!���(!��(!�)!�)!�0)!��H)!�`)!�x)!��)! ��)!-��)!9��)!F��)!R�*!`� *!p�8*!�P*!��h*!���*!���*!���*!��*!��*!��*!�+!��(+!�@+!�X+!�p+!"��+!.��+!:��+!F��+!S��+!_�,!i�,!u�0,!��H,!��`,!��x,!���,!���,!���,!��,!��,!�-!�� -!�8-!�P-!&�h-!/��-!:��-!B��-!J��-!V��-!b��-!m�.!{�(.!��@.!��X.!��p.!���.!���.!���.!��.!��.!�/!�/!��0/!�H/!�`/!�x/!,��/!9��/!C��/!N��/!Z��/!g�0!p� 0!x�80!��P0!��h0!���0!���0!���0!���0!���0!��0!�1!�(1!�@1!�X1!��p1!��1!��1!"��1!.��1!6��1!@�2!H�2!Q�02!Z�H2!c�`2!n�x2!{��2!���2!���2!���2!��2!�3!� 3!��83!�P3!�h3!5��3!K��3!_��3!r��3!���3!���3!��4!��(4!��@4!�	X4!�	p4!��4!��4!��4!��4!
�4!0
5!5�5!R�05!h�H5!}�`5!��x5!���5!���5!��5!��5!��5!��6!	� 6!�86!$�P6!0�h6!=��6!P��6!c��6!s��6!���6!���6!��7!��(7!�@7!�X7!�p7!���7!��7!��7!#��7!6��7!D�8!Z�8!j�08!~�H8!��`8!��x8!���8!���8!��8!��8!��8!��9!
 9!!89!1P9!Ch9!Q�9!`�9!l�9!z�9!��9!��9!�:!�(:!�@:!�X:!�p:!��:!�:!�:!$�:!0�:!B;!W;!f0;!vH;!�`;!�x;!��;!��;!��;!��;!��;!�<! <!8<!1P<!Ah<!O�<!c�<!o�<!x�<!��<!��<!�=!�(=!�@=!�X=!�p=!��=!�=!�=!)�=!9�=!G>!W>!d0>!qH>!`>!�x>!��>!��>!��>!��>!��>!�?!	 ?!8?!!P?!-h?!>�?!L�?!\�?!t�?!��?!��?!�@!�(@!�@@!�X@!�p@!�@!�@!x�@!��@!��@!�A!�A!�0A!�HA!�`A!xA!�A!�A!,�A!;�A!K�A!ZB!g B!|8B!�PB!�hB!��B!��B!��B!��B!��B!�B!C!*(C!6@C!EXC!SpC!]�C!f�C!n�C!v�C!~�C!�D!�D!�0D!�HD!�`D!�xD!��D!��D!��D!��D!��D!�E!� E!8E!
PE!hE!!�E!,�E!6�E!?�E!JF!T@F!��PF!��`F!&�pF!Y��F!���F!��F!���F!���F!���F!	��F!���F!��G!}�G!j� G!^�0G!A�@G!N�PG!�`G!w�pG!=��G!���G!.��G!!��G!���G!���G!���G!���G!h�H!M�H!�� H!2�0H!��@H!�PH!��`H!��pH!���H!���H!��H!��H!^��H!A��H!!��H!i��H!�I!��I!^� I!K�0I!��@I!��PI!�`I!f�pI!t��I!���I!��I!,��I!���I!?��I!���I!^�I!d�I!lJ!uJ!~J!�J!� J!�(J!�0J!�8J!�@J!�HJ!�`J!��hJ!�pJ!�xJ!��J!��J!��J!��J!��J!�J!
�J!�J!�J!!�J!'�J!-�J!3�O!�O!�O!!�O!&�O!/�O!B�O!L�O!O�O!X�O![�L!M!M!M!M! M!(M!0M!	8M!
@M!HM!PM!
XM!`M!hM!pM!xM!�M!�M!�M!�M!�M!�M!�M!�M!�M!�M!�M!�M!�M! �M!"�M!#�M!$N!%N!'N!(N!) N!*(N!+0N!,8N!-@N!.HN!0PN!1XN!2`N!3hN!4pN!5xN!6�N!7�N!8�N!9�N!:�N!;�N!<�N!=�N!>�N!?�N!@�N!A�N!C�N!D�N!E�N!F�N!GO!HO!IO!JO!K O!M(O!N0O!P8O!Q@O!RHO!SPO!TXO!U`O!VhO!WpO!XxO!Y�O!Z�O!\�O!]��H��H��	!H��t��H����5�!�%�!��h�������h��������h�������h�������h�������h�������h�������h��q������h��a������h	��Q������h
��A������h��1������h��!������h
��������h��������h������h�������h��������h�������h�������h�������h�������h�������h��q������h��a������h��Q������h��A������h��1������h��!������h��������h��������h������h �������h!��������h"�������h#�������h$�������h%�������h&�������h'��q������h(��a������h)��Q������h*��A������h+��1������h,��!������h-��������h.��������h/������h0�������h1��������h2�������h3�������h4�������h5�������h6�������h7��q������h8��a������h9��Q������h:��A������h;��1������h<��!������h=��������h>��������h?������h@�������hA��������hB�������hC�������hD�������hE�������hF�������hG��q������hH��a������hI��Q������hJ��A������hK��1������hL��!������hM��������hN��������hO������hP�������hQ��������hR�������hS��������%�!D���%�!D���%}!D���%u!D���%m!D���%e!D���%]!D���%U!D���%M!D���%E!D���%=!D���%5!D���%-!D���%%!D���%!D���%!D���%
!D���%!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%�!D���%}!D���%u!D���%m!D���%e!D���%]!D���%U!D���%M!D���%E!D���%=!D���%5!D���%-!D���%%!D���%!D���%!D���%
!D���%!D���%�� D���%�� D���%� D���%� D���%� D���%� D���%� D���%� D���%�� D���%�� D���%�� D���%�� D���%�� D���%�� D���%�� D���%�� D���%}� D���%u� D���%m� D���%e� D���%]� D���%U� D���%M� D���%E� D���%=� D���%5� D���%-� D���%%� D���%� D���%� D���%
� D���%� D���%�� D���%�� DH�%(fDH�=Q� H�J� H9�tH�� H��t	�����H�=!� H�5� H)�H��H��H��?H�H�tH�� H��t��fD�����=� u+UH�=�� H��tH�=� �	����d������ ]������w������H�WxH�H�J�H�OxHc
H�WH��H)�H����u�PH��H�5'�����fD��H�GxH�OL�H�P�H�WxHcL��PH��I)�E�@(L��H����u-E��uHc�ƇxH�D�H��f�Hc�Ƈ�H�D�H��PH��H�5���]���ff.�f�AUATI��UH��S1�H������Hc�� I��I��$�H��H9,�tJH��H��u��UH�� H��H��L��L������H��L��H���u���H��L��[]A\A]��H�	������ATUSH��H��H�CxH�H�P�H�SxH�SHc�hH��H)�H��H����u.H�Hc�H��H��Hc@(L�$*H�4����I�$HkH�+[]A\�H�5���M���ff.�f���USH��H��H�GxH�/H�P�H�WxHcH�GH�H��H��R(H)�H��H����u8H��h��H��8H��PHE�H��H�����H�EH�+H��[]�H��H�5����ff.���USH��H��H�GxH�/H�P�H��H�WxHcH�GH��H)�H��H����u=A���H��H�5������H��H�@H�0���H�EH�+H��[]�H��H�5}��,���ff.��ATI��USH����H��H�T�H��H������L��H��H���~���H��[]A\�fD��AUATUSH��H��H�GxH�/H�P�H��H�WxHcH�GH��H)�H��H����umH���H��tXH�H��L�hH�i���H�؏H��M��I��H�ӏHD�L��H���r���L��H��H�����L�eH�+H��[]A\A]�f�H��p�H��H�5y��(������AVAUATUSH��H��H�CxH�KH�3H�P�H�SxHcH�ЍjH��H)�H��H�����
��H�H�4��F% =��H�L�h Hc�H��L�$��@
��H�p�F% =��H�H�@ M��xL9(}GH��E1��L���H���I��L��H���g���L��H��H������H�CL�4�LcL�#[]A\A]A^ÐH�@H��N�,�����H�Y�I��M��H�u�HE��fD�H�����H�KI���/�����H�����M���H�5;�����H�=8�1����@��AVAUATUSH�GxH��H�H�P�H�WxH�WHc�hH��H)�H��H������Hc�H��L�$��@
��H�p�F% =ueH�H�@ H�@H��L�(����H���H��M��I��H�y�HD�L������L��H��H�����H�CL�4�LcL�#[]A\A]A^�fD����H�=p�1����H��H�5	�������AVAUATUSH�GxH��H�H�P�H�WxH�WHc�hH��H)�H��H������Hc�H��L�$��@
��H�p�F% =��H�H�@ H��@\tIH��E1�����H���I��L��H���!���L��H��H�����H�CL�4�LcL�#[]A\A]A^�L�hHH�����H�6�I��M��H��HE��f�����w���H�=h�1����H��H�5����@��ATUH��SH�GxH�P�H�WxH�HcH�WD�a(H��XH��H)�H��H������Hc�H��H�H��@
��H�p�F% =udH�H�@ E��u(H�xu4H��hH�H]H�][]A\�f.��@��������t5H��PH�H]H�][]A\�fD���H�UH��D����	��w��H��H�5R���H�=Y�1��n�ff.���USH��H��H��H�CxH�+H�KH�P�H��H�SxHc�PH��H)�H��H����unHc�H��@
tSH�p�F% =u1H�H�@ �@
tMH�pH�����H�EH�+H��[]�f.��H������H�=��1���H�5����H�=��1���f���USH��H��H��H�CxH�+H�KH�P�H��H�SxHc�PH��H)�H��H����u'Hc�H��@
t&H�pH�����H�EH�+H��[]�H�5��.�H�==�1�����AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#��H�PH�CL�$�Hc�H�,�H���@
��H�p�F% =ufH�H�@ �P)L�l)��Љց��A�D$E։������҃�uc���tZ��I�T$A�D$M�eHkH�+H��[]A\A]���H����H�K�DH�����H�KI���B���@L��H���%��H�5����H�=�1����f���AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =t�H����H�SA�D$L�l*�������uI���t@I�D$��A�D$M�eHkH�+H��[]A\A]Ð���H�SI���j�����L��H�����H��H�5	���H�=S�1���f���AUATUSH��H��H��H�CxH�3H�P�H�SxH�SHc�hH��H)�H��H������H�C�@#��H�HH�CL�$�Hc�H�,�H��@
��H�p�F% =uVH�H�@ H�HA�D$L�l*����������ub���tY��I�T$A�D$M�eHkH�+H��[]A\A]�fD�H����H�S�DH����H�SI���R���@L��H�����H�5dž�w�H�=��1��Y�f���AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#��H�PH�CL�$�Hc�H�,�H���@
��H�p�F% =uVH�H�@ H�L�l)��P\A�D$����������u_���tV��I�T$A�D$M�eHkH�+H��[]A\A]��H���S�H�K�DH���@�H�KI���R���@L��H���u��H�5���7�H�=�1���f���AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#��H�PH�CL�$�Hc�H�,�H���@
��H�p�F% =u^H�H�@ H�@L�l)��PCA�D$���������҃�ub���tY��I�T$A�D$M�eHkH�+H��[]A\A]�fD�H����H�K�DH����H�KI���J���@L��H���-��H�5�����H�=��1�������AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#��H�PH�CL�$�Hc�H�,�H���@
��H�p�F% =u^H�H�@ H�@L�l)��P@A�D$�����������uc���tZ��I�T$A�D$M�eHkH�+H��[]A\A]���H�����H�K�DH����H�KI���J���@L��H������H�5u���H�=|�1������AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =t�H�����H�SA�D$L�l*�������uI���t@I�D$��A�D$M�eHkH�+H��[]A\A]Ð��H�SI���j����1�L��H�������H��H�5m���H�=m�1��l�ff.�����������AVAUATUSH��H��H�CxH�P�H�SxH�SHcH�H�3D�`H�‹i(H)�H��H������H�C�@#��H�HH�CL�,�Ic�L�$�H��@
��H�p�F% =uYH�H�@ ��uF�hA�EN�t"���������uc���tZ��I�UA�EM�nLcL�#[]A\A]A^�#h��H���K�H�S�DH���8�H�SI���O���@L��H���m��H�5��/�H�=�1������AUATUSH��H��H��H�CxH�KH�P�H�SxHcH�H�3�hH��H)�D�j(H��H������H�C�@#ttH�PH�CL�$�E��uS�ShA�D$Hc�L�l��������u^���tU��I�T$A�D$M�eH�CH��H�H��[]A\A]�fD�����H���0�H�KI����L��H���e��H�5x~�'����AVAUATUSH�GxH��L�'H�P�H�WxH�WL��HcD�hH��H)�H��H������H�GM�t$��@#��H�HH�GH�,�Mc�J��@
��H�p�F% =uJH�H�@ �H(H�H��H���a��E
 �E�@ugH�C L)�H��~;I�nL�#[]A\A]A^��H���#�뮐��H�SH���q����L��L���H���5�I��L�`�@H��H�����H��H�5#~���H�=~1����ff.���AWAVAUATUSH��H��H��H�CxL�H�KH�P�L��H�SxHc�PH��H)�H��H�����Hc�M�h�H��@
��H�p�F% =��H�H�@ H�$H�$H�8xzH�$M��1�H�@H�D$�M��H����H�^|H��I��H�D$L��L�$�H�n|M��HE��	�L��H��H���{�H�C L)�H��~OH�$M�nM�~H��H9(}�L�+H��[]A\A]A^A_���H����H�$�L���f.��L��L��H����I���H�=�{1��Z�H�5�|�^�ff.���AWAVAUATI��H��USH��I�D$xI�$I�L$H�P�H��I�T$xHc�PH��H)�H��H������Hc�L�{�H��@
��H�p�F% =��H�L�h I�}��I�D$�@#�H�PI�D$H�,�M�uH��zH��L��H�#{I�H��H�L$HD���H�L$L��H��H�����E@��I�D$ L)�H����I�oI�}����
�L��I�D$ H)�H��~PI�4�L��L�{H����H�CI9m}�M�<$H��[]A\A]A^A_���L����I������H��H�޹L�����H����L����H�����I���L��L���L����I��H�X�,���f�H��L��������H�5�|�T�H�=�y1��6�fD��AUATI��H��USH��I�D$xI�$I�L$H�P�H��I�T$xHc�PH��H)�H��H������Hc�H��H��@
��H�p�F% =u}H�H�@ H�I��H�hH��u
�1DL��I�D$ H)�H��~0H��L��L�k�q�H�CH�mH��u�M�,$H��[]A\A]�DH��H�޹L���}��H�����L���#���x���H�=!y1�� �H�5�$�@��ATUSH�GxH��H�H�P�H�WxH�WHc�hH��H)�H��H������Hc�H��L�$��@
t{H�p�F% =u=H�H��8H�@ H��@]�u@H�����H�SH��LcL�#[]A\�f.���V��H��8H��@]�t�H�p8H�����H���H�=x1��7�H��H�5�y�8����AUATUSH��H��H�GxH�P�H�WxH�HcH�WD�i(H��hH��H)�H��H������Hc�H��L�$��@
��H�p�F% =ulH�H�@ H��P\E��tB��ue��t=H�p(H����H��H�����H�SH��LcL�#H��[]A\A]����u1����H�p0�f���&���@H�p(H������H��H�5�x�#��H�=�v1���D��ATUSH�GxH��H�H�P�H�WxH�WHc�hH��H)�H��H������Hc�H��L�$��@
tlH�p�F% =uMH�H�@ H�1��@\u+H����H��H������H�SH��LcL�#[]A\�@H�pH��f.���6���H�=v1��6��H��H�5�w�7�����ATUSH��H��H�CxH�KH�P�H�SxH�6HcD�f(H�3�PH��H)�H��H������Hc�H�,�H���@
��H�p�F% =uwH�H�@ E��u3H�H�p H�����L�cH��H������I�I�$HkH�+[]A\�f�A��tJ1��@t�H�H�@H�RH�D�H�0H��t��@��t�H�6�fD�H������~���fDH�@H�pH�w���H�5�z���H�=�t1����f���AUATUSH��H��H�GxH�P�H�WxH�HcH�W�i(H�D�`H��H)�H��H������Mc�J��N�,��@
��H�p�F% =ulH�H�@ ���@��HЃ�tc��t.H�0H����H�SJ��LkL�+H��[]A\A]�f��0H�����H��H���z����������@�0��H�=:t1�����H��H�5&t����ff.�@��AVAUATI��USH�GxH��H�/H�P�H�WxHcH�GH��H��D�jH��H)�H��H��������H��Hc�H�4ȋV�� ����H�L�r Mc�J��@
�iH�p�F% =��H�L�h M��xM9u}3H�C H)�H����H��1�L�e����H�EL�#[]A\A]A^�DM��tsH�C H)�H����I�EH��L�eJ�4����H�EL�#[]A\A]A^���H�����I��H�C�:�����H���s��I���M���H�H�P�H�CxH�H��H�CxH;��tiH��H+SL��H��H���[]A\A]A^���H��H��H���M��H������DH��H��H���-��H������DH�����H��H�=�q1�����H�5FrL������fD��AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#��H�PH�CL�$�Hc�H�,�H���@
��H�p�F% =uVH�H�@ H�A�D$L�l)���������ue���t\��I�T$A�D$M�eHkH�+H��[]A\A]�f��H������H�K�DH�����H�KI���R���@L��H�������H�5�r���H�=Cp1����f���AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =uYH�H�@ H�L�l*�HcP`A�D$��������ud���t[��I�T$A�D$M�eHkH�+H��[]A\A]���H�����H�S�D�s��H�SI���R����L��H������H��H�5�p�d��H�=o1��F��fD��AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =t�H�����H�SA�D$L�l*�������uI���t@I�D$��A�D$M�eHkH�+H��[]A\A]Ð�K��H�SI���j����1�L��H���k����H��H�5�n�:��H�=�n1����ff.����AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =uQH�H�@ L�l*�H�PA�D$��������u_���tV��I�T$A�D$M�eHkH�+H��[]A\A]��H�����H�S�D���H�SI���Z����L��H���-���H��H�5�r���H�=�l1�����ff.���AUATUSH��H��H��H�CxH�3H�P�H�SxH�SHc�hH��H)�H��H�����
H�C�@#��H�HH�CL�$�Hc�H�,�H��@
��H�p�F% =ufH�H�@ �P�� ��u^H�H�@ H�KL�l)�A�L$�΁�����ul���tc��I�D$A�L$M�eHkH�+H��[]A\A]úH������뒐�H��H������fDH�����H�SI���2���@H��L��H�������H�=�k1����H�5iq���fD��AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�PH��H)�H��H������Hc�H�4�H�,��F% =unH�L�h H�C�@#twH�PH�CL�$�H�CA�L$Ic�L�l(���%�����ud���t[��I�T$A�L$M�eHkH�+H��[]A\A]���H�����I��H�C�@#u�H���n��I���f�L��H������H�5k�g�����AVAUATUSH��H��H�CxH�KH�3H�P�H�SxHc�PH��H)�H��H������Hc�H�,�L�4�H�C�@#tUH�PH�CL�$�A�D$L�l)�������uJ���tA��M�t$A�D$M�eHkH�+[]A\A]A^��H�����H�KI����L��L��H������H�5_o�|��ff.����AUATUSH��H��H��H�CxH�KH�3H�P�H�SxHc�hH��H)�H��H������H�C�@#tcH�PH�CL�$�A�D$Hc�H���L�l��������uN���tE��I�T$A�D$M�eH�CH��H�H��[]A\A]�fDH�����H�KI����L��H������H�5�g���ff.�@��ATUSH�GxH��H�H�P�H�WxH�WHc�hH��H)�H��H������Hc�H��L�$��@
t_H�p�F% =u=H�H�p 1�H���L��H��H�����H��H���F��H�SH��LcL�#[]A\�f�����H���H�=bh1����H��H�5�j���@��ATUSH��H��H�CxH�+H�KH�P�H�SxHcH�6�PH��D�f(H��H)�H��H������Hc�H��@
��H�p�F% =uTH�H�@ E��t(H�@H��8H��H��tHcP���u;H�p�	DH�pH�����H�EH�+[]A\���H������뤐�LH��H����� ������H���H�5g���H�=�f1����f���AVAUATUSH��H��H�CxH�+H�KH�P�H�SxHcH�6�PH��D�f(H��H)�H��H������Hc�H��@
�{H�p�F% =��H�L�p A����A����H�C�@#toH�PH�CL�,�A�E����ƒ���������!�E����I�V���f����������I�UA�EL�mH�+[]A\A]A^�@H���p��I����H���[��I��A���S���I�FI�H�������H��HpH��HQ��R��H�EH�+[]A\A]A^�f���t<��M�uA�E�p���@I�FH��H������H�EH�+[]A\A]A^�DL��L��H������1���DL��H���������H�=�d1����H�5�j���ff.���AUATUH��H��SH��H�ExH�]H�MH�P�H��H�UxHc�PH��H)�H��H������Hc�H��H��@
�xH�p�F% =u@H�L�h I�EH�xL�`tIL��H�����H�I9�u>H�]H��[]A\A]�f��H������I��I�EH�xL�`u�1�I9�t�L��H������I�EH�xL�`tL��H�����H�I)�M���H�E H)�H��L9�},�f�� H�����H�CI�t$H��H�����H�1�L��H�����I��H���:���I�D$H��HcPH��t���t�Du��H���'��H�C뢐H�@H��t�H��H���L��H�C�fDH��H��L��H�����H���|���H�5}c����H�=tc1����ff.�f���AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =uYH�H�p H���Z��H�SL�l*�HcA�D$��������u\���tS��I�T$A�D$M�eHkH�+H��[]A\A]úH�����H���fD���H�SI���R����L��H������H��H�56b���H�=-b1��f��fD��AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H������H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =uiH�H�p H���:��H�SA�L$���L�l*��ʁ������ƒ�@��t_H��xZ��I�D$A�L$M�eHkH�+H��[]A\A]���H���S��H���fD�C��H�SI���B����H��L��H���r���H��H�5�`�1��H�=�`1������ATUSH��H��H�CxH�KH�3H�P�H�SxHc�PH��H)�H��H������Hc�H�,�H���@
tsH�p�F% =u:H�H�@ H��B]�u@H�r8L�cH���J��I�I�$HkH�+[]A\���H���S��H��B]�t�H��H�����H���H�=_1��<��H�5�`�@����USH��H��H��H�CxH�+H�KH�P�H��H�SxHc�PH��H)�H��H����uiHc�H��@
tNH�p�F% =u)H�H�x ���H��H���z��H�EH�+H��[]�@H�ߺ���H����H�=]^1����H�5�_���ff.��ATI��USH���Q��L��H��H�����H��� H��H�߉�H���[��L��H��H������H��[]A\�D��ATUSH��H��H�CxH�+H�KH�P�H�SxHcH�6�PH��D�f(H��H)�H��H�����|Hc�H��@
taH�p�F% =u8H�H�@ H�1��@\u	E��t1H�p0H���%���H�EH�+[]A\�f��H���c���H�p(��H�=1]1��\��H�5�^�`��AUATUH��SH��H����I��H��F!���c!�I�D$ H)�H���%H��L��L�m���H�E�C f%�f�� ��f=���H�7� %���%=��L��=	u5H�sHL��L���^���H�s@L��H���O���H�s8L��H���@���H��DH�H��t
�C!�L���H��H��[]A\A]��H�sPL��L������H����@�C"L��@t���y�H�C(�@!@�[��H�@L��L��H�@(H�@(H�0���H���@H�s0L��L�����H���i����H��H��L���
��H�����D��USH��H��H��H�CxH�H�sH�H�I��H�KxHc�HH��I)�L��H����uaHc�H�j�H��@
tBH�p�F% =uH�H�p H��H������H�H��[]Ð�H���3���H����H�=;\1��0��H�5�\�4��@��USH��H��H��H�CxH�+H�P�H�SxH�H��J(HcH�CH��H)�H��H����u+��H���H��HD��H���R���H�EH�+H��[]�H�5	Z������AVAUATUSH��H��H�CxH�+H�P�H��H�SxH�SHcH��D�hH��H)�H��H��������H��Hc�H�4ʋF% =��H�Lc` Ic�H��@
�rH�p�F% =��H�L�h E��x[A�E���I�EH�S H�@H)�H��xL9���H����H��1�L�u�y��H�EL�3[]A\A]A^�f�H�S H)�����H���s���H�SLc��H�����H���S���I���[���L��H�������x�A�E���L��H�����H�S H�H)�L9��Q���H��~LI�EH��L�uJ�4�����H�EL�3[]A\A]A^��H��H��H���
���H������DH��H��H�����H���H�5�Y���H�=�Y1����I�EH�S H�@H)����f.���AWAVAUATUH��H��SH��H�ExH�]H�MH�P�H��H�UxHc�PH��H)�H��H�����-Hc�H��H��@
�
H�p�F% =��H�L�p A�F���I�H�@H��H��?��tlI�FE1�H�D$�BfDI�H�@I9�LH�E H)�H����H�D$H��L�{A��J�4��[��H�CL��Mc�A�F�t�L��H���߿��H�I9�~�H�]H��[]A\A]A^A_�D�H���C���I��A�F��O���L��H��蚿������H���H��H�޹H���M���H���a���H�=�W1�����H�5�e����ff.���AUATUSH��H��H��H�CxH�3H�P�H�SxH�SHc�hH��H)�H��H������H�C�@#��H�HH�CL�$�Hc�H�,�H��@
��H�p�F% =u^H�H�@ �@�udH�H�PH�CA�L$L�l(���%�����up���tg��I�T$A�L$M�eHkH�+H��[]A\A]�@�H������@�t�H��H���J���Hc��DH������H�SI���:���@L��H������H�5<d追��H�=�V1�衾�����AVAUATUSH��H��H�CxH�KH�3H�P�H�SxHcH�ЍjH��H)�H��H�����@��H�H�4��F% =��L�nHc�H��L�$��@
�H�p�F% =��H�L�p �H�=�UL����������H�=�UL�������tL�H�=�UL���������H���6���H��PI9Ft.H�CH��LcL�#[]A\A]A^ÐH��舺��H��PI9Fu�H��h��f��1�H����H�KI���
���D�H���#���I���'���H���p����u���H�5U����H�=U1�����L��H�=U1�����USH��H��H��H�CxH�+H�KH�P�H��H�SxHc�PH��H)�H��H����u~Hc�H��@
tcH�p�F% =uAH�H�@ H�@H�pHH��tH��H���1���H��H���&���H�EH�+H��[]���H���3����H�=S1��3���H�5�X�7������AVI��AUATUSH�GxH�P�H�WxH�HcH�WD�i(H��hH��H)�H��H������Hc�H��L�$��@
��H�pH���F% =ukH�H�@ H�@H����A��H�D����t2��uI�0H����H��H���Ȼ��H�SH��LcL�#[]A\A]A^�H�0H����������&����D��H�=�t1��#���H�5�WL���$���I��@]�u:H�@8H�:SH��tH�H�P H��H�5'SH��1��O���H�=�Q1��Ѻ��L��H��薺���@��AVAUATUSH��H��H�CxH�+H�KH�P�H�SxHcH�6�PH��D�f(H��H)�H��H�����/Hc�L�m�H��@
�H�p�F% =u,H�L�p A���H�$vJc�H�>��f.��H������I����fDA�~r��M�f H�����L��H��H�EH������H�+[]A\A]A^�A�~r��I�v 1�H��t"H�NH�6�����H��HAH��HVH��H�߹諸��H�EH�+[]A\A]A^�H�C L)�H����I�6H��8H��tH���A���I�E�i����E�fH���#���L��H��H�EH������H�+[]A\A]A^�DI�v��H������H�E�����E�f�f�M�f�����I�v H��脼��H�E����I�v(H��t'I�VH���
���H��H���t脺��H�E���H�����;���H�E���L��L��H��菵��I��H�h���H�=�P1��E���H�5�P�I���H�=Jr1��+���H�=r1�����L���6���D��AUATUSH��H��H��H�CxH�KH�P�H�SxH�6HcD�f(H�3�PH��H)�H��H������Hc�H�,�H���@
��H�p�F% =��H�H�@ A�����HA����E��t2L�`�������
�L�������H���s����������ʁ���
���1�E1��@fD�H�����A���m����BH����H����L�`(H�P�L�kL��H���ߵ��I�I�EHkH�+H��[]A\A]�fDL�`��t?����
t1H��H�P�H��� L�`��H�R��M�d$�ȐM�d$��fDH�H�@�� ��H�RL�`�R���H�5S�$���H�=M1�����H�=?p���f.���AUATUSH��H��H�GxH�H�P�H�WxH�WHc�hH��H)�H��H�����H�G�@#��H�HH�GL�$�Hc�H�,�H��@
��H�p�F% =uqH�H�@ �P�� ��uqH��@(H�CL�l(�A�D$�����u~���tu��"A�D$I�$�@(M�eHkH�+H��[]A\A]�fD�H���۱���f��H��H�������fD賶��H�SI���"����L��H���%����H�=�K1�蕴��H��H�5yQ薳��fD��AUATUSH��H��L�gH�dH�%(H�D$1�H�GxH�P�H�WxHcH��hI��H)�D�j(H��H������Hc�H��I�I�$�@
��H�p�F% =u]H�H�@ H�H�@ E��tgHc�H��hH��PH9�H��HD�I�$HkH�+H�D$dH3%(u^H��[]A\A]�f��膰��L�cH�I�H�@ E��u�H��H��H��H�� ȉD$ʉ$��|���I�$��A���H�=DJ1��C���H��H�5'P�D���@��AUATUSH��H��H�GxH�P�H�WxH�HcH�WD�i(H��hH��H)�H��H�����nHc�H��L�$��@
�GH�p�F% =u4H�H�@ A��H0D�������H��nHc�H�>����n�����@H�6H�����H��H���²��H�SH��LcL�#H��[]A\A]��H�6H��赳��H��H��芲�����Hc6�H�6H���͵����6��6�@�6�{���H�6H��1�蓱��H��H���8����q����H���$���H��H�������R���@��H��辰���7���D��H�=�k1�舱��H�={H1��z���H��H�5^N�{���ff.���ATUSH��H��H�CxH�KH�3H�P�H�SxHc�PH��H)�H��H����u~Hc�H�,�H���@
t[H�p�F% =u6H�H�p H�����L�cH��H���@���I�I�$HkH�+[]A\�D�H��諭��H���H�=�G1�訰��H�5�M謯��ff.����AWAVAUATUSH��H��8H�GxL�/H�P�L��H�WxHcH�GH��D�bH��H)�H��H������Ic�I��H��H�L$L�4��B
��H�r�V�� ��u}H�L�z ��Hc�H��@
��H�p�F% =uoH�H�@ A�W M�g0f��f�����f�����f���tMH�CJ�D0�H�H��8[]A\A]A^A_�f���v���I��H�C�t���f.��H���S���뉐H�I�|$�M�<$H�@HH�|$(H�@H�@H�D$H���eH�C L)�H��H9��QL��H��I�m蒰��H��H���g���I�EL�-@k@L����H��
��IcD�L�>��D�D$I�T$H�t$1�H��I�D$L�uH�D$ �Q���H��H�0�f���L�d$ H�EL��L��M����0A��@H�����-H�� ��H��0�"I�T$H�t$1�H�����H��H�0�
���H�EM����H�CL�d$Ld$(J�D�H�H��8[]A\A]A^A_���D$I�t$I�D$H��L�uH�D$ �p���H��H���E���L�d$ H�EL���:���@�D$�f��D$���fD�|$�<���I�t$H�������fDI�t$H������H��H���ح��H�EM���.���I��H��I���b���f.�H���
���M������I���=���DH�C L)�H���pL��H��蕮��H��H���j���I�ELsL�3H��8[]A\A]A^A_�H�C L)�H���OI�4$H���S���H��H���(���H��I�EI�t$�7���H��H������H��PI�EI�T$H����H��I�����I�EL�+H��8[]A\A]A^A_ÐL��M����0A��@H���������@M�|$H��M�t$M��L��踬��H�}H�|$H��H��脬��H�EH�l$����fDL��M����0A��@H���v������@H�5dD��H��1�蜭��H���A���@H�L$(L��L��H�����I�����DL��L��H���ͨ��I���u���DL��L��H��譨��I�����H�=rC1��g���H�=.B1��Y���H��H�5�C�Z���f.���AVAUATUSH�GxH��H�H�P�H�WxH�WHcH��D�`H��H)�H��H������Mc�J��N�,��@
��H�p�F% =��H�L�p ��Hc�H��@
�KH�p�F% =��H�H�@ A�N I�n0f��f�����f�����f���tqH�5�@H��1��(���H��H��譪��H�SJ��LkL�+[]A\A]A^�D�����H�SI���T���f.��H�����j���fDH��L��H��蚪����H��H��H�5IB1�茫��H��H���!����o���@H�MH�UH��1�H�5B�_���H�MI��H��uL��H������6���H����H��AH��1��i�����H�=.@1��Y���H��H�5�A�Z���H�=GA1��<���ff.����H�GxH�SH��H�H�H��H�OxHcH�GH��H)�H��?H��H�H��H)�H�蛦��H���Hc
m� H�@H��H�
H�H�Q8H�H�@ H�P8H��8H�PH��hH��PH�PH�XH�@(H�@0[�D��AWAVAUATUSH��H��H��L�3H�KdH�%(H�D$1�H�CxH�P�H�SxHcH�6�PH��D�f(L��H)�H��H������Hc�L�,�A���A�E��u<t%��=
����H�5@H�����H��A�EE���W% =�I�EM�mH�PH�$L�=9@H�����A�E<"�#<\�CE��@��H����@��t<?�E����<$u���~<@u����H�s� ��H������@@��@@�<
��<
�<	�8<�X<�x<��<u	@����L��H��H��1��Ӥ��H�$I��H�P�H�$H���'���A��H��H��H�??�ڣ��I�.L�3H�D$dH3%(��H��[]A\A]A^A_Ð� �����H���M���I�UA�H��H��H�JL��L�-�>H���6���I�����uQ�p����A�t$L���2���A��H���L��H��H��I���,���@A�G���$���M�|$A��H�c><"tBA��H�P><$t,A��H�=><@t<\�l���A��L��H��H��賢��L��M��I����A��H��H��H��=胢���n���fDA��H��H��H��=�[����F���fDA�L��H��H�߹�7����"���f���H�5^=H�����H��A�E% =��I�E�0@��'�@��\��H�֥ @��H���<���@@��@@��@��
��@��
�@��	�4@���R@����@����@���\H��<H��H��1��(����A��H��H��H��<�C����.���fDA��H��H��H�g<��������fDA��H��H��H�Z<������fDH��L��H���5���H�$I�����f�A��H��H��H�
<裠�����fDA�}?�?�����`����1�L��H���Ρ���m���f���H�5><H���'���H���e����A��H��H��H�v;��������fDA��H��H��H�B;������fDA��H��H��H�;�˟�����fDA��H��H��H��:裟�����fDA��H��H��H��:�{����f���fDA��H��H��H��:�S���A��H��H��H�z:�6����W����H�j:�f���@A��H��H��H�I:����뮐A��H��H��H�;:���뎐A�H��H��H�߹�Ǟ���o���f�A��H��H��H��9裞���K���fDA��H��H��H��9�{����#���fDA��H��H��H��9�S������fDA��H��H��H�}9�+�������fDA��H��H��H�^9�������fDA��H��H��H�09�۝�����H�5}=蚟���u���D��AVAUATUSH�GxH��H�oH�H�P�H�WxHcD�hH�D�H)�H��H������Mc�N�$�L�H�u�F% =u.H�Lcp H�����H�EA���v2LcL�#[]A\A]A^�f���֜��H�kLc�L���f.�H�� H��H�u8J��H�CJ�4�1�����LcL�#[]A\A]A^�H��H�5B8蝞��ff.�f���AWAVAUI��ATUSH��H�GxH�oH�H�P�H�WxHcD�xH�D�H)�H��H������Ic�L�4�H�D$L�H�u�F% =��H�^L����H�޹H�=�7H�EH�SL�%-� �����HD�E1��I��I���tcK�4�H��藝����u�Ic�I�EH�L$L��H�4��;���MuM�uH��[]A\A]A^A_�@�1�����I�mH��L��Z���DH������H��H�5E6�X������AWAVAUATUSH��H��H�GxH�/H�P�H�WxH�WHcI��D�hH��H)�H�GH���@#��H�pH�GH��L�4�Hc5o� H���L��E�x8��~<A�D$H�H�4�H��t,�F� ����uy<tu�ǁ���
teDA�FMc�Ic�N�d�����������������I�VA�FM�t$H�CJ��H�H��[]A\A]A^A_�f���tCH�H����H�@H����A�@8H�K�p������H�SI��H������@��tc��t
H�H�y u��t6H�f�f.@(z�t&�D�H��L�D$覙��L�D$��u�H�SH�������L��H��赚���(���1�H��L�D$�q���L�D$��f.�H��t�H�F�80�=����ff.��AWI��AVAUATUH��SH��H��H�$H��L��M�7�ǝ��H�
�� Hc�� H���L�,�I���L�$�H������H#EH9�u*H�MH��t!H������H#AH�H9��1L��虝��L��L��H��H��踜��H��H��H��L���'���A�D$8��tXI�GxH��I�GxI;����L��I+WH���I�G L)�H����M�fI�n�L��M�'H�5�4M��膘��I�GxH��I�GxI;���eL��I+WH���I�G L)�H���(M�NI�nH�4$L��M���4���H��t5�C"��H��L���j�����u�C f%�f=�t
H�[HH���u���H��H��[]A\A]A^A_���Q��%��_���A���€��Q�������H�H�x�����H�8H�L$������L��L���g���H��L��H��艘��H�L$�z����L�c(M���6���H�$H��L��L�����H��A�D$!@����M�d$M��u�����L��L���L�����I�����DL���p������L��L���L��赖��I���5���DL���@�������H��H�L$�[���H�L$�A�€��Q����������ff.���ATUSH��H��H�CxH�KH�3H�P�H�SxHcH�ЍjH��H)�H��H��������H�H�4��F% =uWL�fHc�H�,�H���@
t|H�p�F% =uKH�H�p H��8L��H���R���H�CH�D(�H�[]A\Ð�1�H������H�KI�����H���C���H���H�51�R���H�=11��4���@AWE1�M��A�AVAUI��ATI��UH��SH��j���ZYH����L�pH��A�F��u�ЍJ���v������
u(L��L��L��H���_���H��H��[]A\A]A^A_�D��t��M�~A�FA�O����L��H��舕��A�F��L��H�5�QH��1��Ζ��ff.���ATUSH��H��H��H�KH�3dH�%(H�D$1�H�CxH�P�H�SxHc�PH��H)�H��H�����UHc�H�4�H�,��F%  =�<H�H�xH�FH�<$H�
6� ��H���0L�-SIc4�L�>������
���1��p���
���1��p���
���1��p
���
���1��p���
���1��p���
���1��p
���
���1��p	���
���1��p���
���1��p���
���1��p���
���1��p���
���1��p���
���1��p���
���1��p���
���1��p�����
���1�‰��
‰��1��A‰��
Љ��1��AЉ��
Љ��1��AЉ��
Љ��1��AЉ��
Љ��1Ѝ����1Љ���H�5�-H��1�衖��L�cH��H���2���I�I�$HkH�+H�D$dH3%(�H��[]A\��H��H���%���H�<$���@H�QL�aI��A��I��A��H�modnarodH�setybdetH1�H1�I�H��8H�uespemosI�arenegylM1�I1�H��@L�I�H��
H��L1�I�� L1�I�H��L1�I�H��I�H��L1�L1�I�� M1�I9�u�I)�I�p�L��PH��H�D�Kc4�L�>���pH��0H	��pH��(H	��pH�� H	��pH��H	��pH��H	��pH��H	��H	�H1�I�H��
I�H��L1�H��I�� H��J�4L1�H��M�H1�H��H�� L1�L1�H�9@���H��
H1�H�H��H1�H�� H�H��H�H��H1�H1�H�� H�H��
H1�H�� H�H��H1�H�H��H�H��H1�H1�H�� H�H�H��
H��H1�H��H�1H��H1�H��H1�H�� H1�1����虐��H�5�/譑��ff.�f���AWAVAUATUSH��H��8H�GxH�P�H�WxH�HcH�WD�y(H��hH��H)�H��H�����v
Hc�H��L�4��@
�>
H�p�F% =�tH�H�@ H�D$A��8�
Mc�L�%ĉ 1�L��H�5�*H��L��xH�@�|$'H��H�D$踑��H�����@
��L�XA�{L�\$��H�t$H������H��E1�E1�j1�H��H��jjL�\$0L��H�D$H�ڑ��H�� L�T$(M��tA�R���w��A�RH��tkH�@H��tb�@
t\H�p�~uR�L$'H��H��E1�jH�T$(A� ���^_H��t*H�H��t"H�CH��LsL�3H��8[]A\A]A^A_�@I��M�A�D$	<twA�L$
HL$<��H��MHc�H�>���膍��H�D$���@�1H�����H��H���Ӑ��I��H�CL�$�LsL�3H��8[]A\A]A^A_�f�A��8��H�
?MD��Hc�H�>��f�H�11�H���ӏ��H��H���x���I���H�1H�����I���H�1�r�����1�b����H�1H���U���H��H���*���I���R���f�H�1H���u���I���=���1�H���S���H�t$H��I��H���0���A�D$����<��%��=
��A�T$������A�T$1�H���
���I������1����H�t$1�1�H�����1�H�����H�D$A�����p!A����A��/��A��0��A��1�BA��2�DA��3�F@��@���>���@H�D$H��� H�5�'H���@ %�H��1��V���H��H�����I��H�H�x
�
���L��� �
�
f�ID$�H��A���z��@��@D׃��I�$Hc�H;Br����H�D$�@ f�D$f%�A���f=~��H�C� %�H�4�1����H�t$H��莏��H��K��H�4��F���H�D$1��@!@�����H�p���H�D$L�`(�@ f�D$f%�f��"��L���Z���L��H��H��藌��I�����H�D$H��H�P8H��(L�,�A�}���8���I������H�D$H�P(H��8H��H��t�P���fH��8���H�D$1��@ f�D$f%�f=��k���H�D$H�p0�]���H�D$H��H�P8H��(H�4и�~HE��z���I���B���H�L$1��A f�D$f%�f=�����H�q(����H�D$1��@ f�D$f%�f=��`���H�D$H�p(�R���H�|$���H��H������I������H���*���H�6%I��H�D$L�hHL��H���<���L��H��H��讍�����H�D$Hc
�� A�H���H�@@H���J;���I��I���u�H�H�pH��荍��H��I��袍��A�UH��I��H��� H��L��贌��L��H��H��I���#���H��1�L��jE1�E1�L��H�����A�UXY������A�U����H�D$�@ f�D$f%�f=��H�D$H��H�pH���I�����H�D$H�@(H��������@!@�p���fDH�@H���]���H���@!@�O�����H�D$1��@B����H�PPH��8H�4�H��������F�HH�H�PH�FH�D�H�0H��������xtH�6H�������H��1��<���H�D$H�p0H�������H���
���H�����H�D$1��@ f�D$f%�f�� ����H�D$H�pP����H�D$H��H�P(H��8H�4�轍��I�����H�T$��H�=�D1��߉���L��H��H�D$����H�D$�v���L��H���s���I���;���薋��I��A��&�I�UI�uH�������H��HBH��H��HNL���[���A�E ��A�L$ ���H���:���H��I�������p �����H������H��I��H�D$L��H�PH譊�����f=~�?H�G� %�H�4�1����H�D$�@#� t����L���H���݇��I���E���1���t!H�H�@H�RH�D�H�0H��t	�xtH�6H����H���Z���I�EL��H�ߋP8�X�����@�������1�1��$���@�������H�t$�H����1�H�����@�������A��$L��H�ߍ�H��H�����I���}���H�=�1��߇��D��H�=�B1��·��H��H�5a �φ��H�t$�H���m���1�H���x���@��������@��������@�������L��H���Ĉ�����L��H��贈������H�t$H�=] 1��L���ff.����AWL�W H��1�AVH�
N H�O AUATL�%�~ USH�����
H��萇��H�Y���H�5' H��A������H�����H�5 H����H�����H�5 H���ۆ��H�����H�5 H���ņ��H�n���H�5 H��H��@(襆��H�N���H�5�H��H��@(腆��H�>��H�5�H��H��@(�e���H���H�5�H��H��@(�E���H����H�5�H��H��@(�%���H���H�5�H��H��@(����H���H�5�H��H��@(���H�~�H�5�H���υ��H�X���H�5~H��蹅��H����H�5sH��装��H���H�5nH��荅��H���H�5dH���w���H��H�5XH���a���H�ʰ��H�5JH���K���H�d���H�5@H���5���H�N���H�55H��H��@(����H�n��H�5$H��H��@(���H�N��H�5
H��H��@(�Մ��H�.��H�5�H��H��@(资��H�����H�5�H��H��@(蕄��H�>��H�5�H������H���H�5�H���i���H���H�5�H��H��@(�I���H���H�5�H��H��@(+�)���H�r�H�5�H��H��@(�	���H�R�H�5�H��H��@(���H�2�H�5�H��H��@(�Ƀ��H��H�5nH��H��@(詃��H���H�5aH��H��@(.艃��H���H�5LH��H��@(-�i���H���H�5:H��H��@(*�I���H���H�5'H��H��@(�)���H�r�H�5H��H��@(�	���H�R�H�5H��H��@(���H�2�H�5�H��H��@(�ɂ��H��H�5�H��H��@(,詂��H���H�5�H��H��@(!艂��H���H�5�H��H��@(�i���H���H�5�H��H��@(�I���H���H�5�H��H��@(
�)���H�r�H�5�H��H��@(	�	���H�R�H�5�H��H��@(5���H�2�H�5H��H��@(6�Ɂ��H��H�5qH��H��@(8詁��H���H�5]H��H��@(艁��H���H�5JH��H��@(�i���H���H�58H��H��@(2�I���H���H�5'H��H��@(3�)���H�r�H�5H��H��@(�	���H�R�H�5�H��H��@(���H�2�H�5�H��H��@(�ɀ��H��H�5�H��H��@(4詀��H���H�5�H��H��@(艀��H���H�5�H��H��@(�i���H���H�5�H��H��@(0�I���H���H�5�H��H��@(�)���H�r�H�5�H��H��@(�	���H�R�H�5oH��H��@(/����H�2�H�5\H��H��@( ����H��H�5JH��H��@(1���H���H�56H��H��@(���H���H�5"H��H��@(�i��H���H�5H��H��@((�I��H���H�5�H��H��@(�)��H�r�H�5�H��H��@('�	��H�R�H�5�H��H��@(
��~��H�2�H�5�H��H��@(��~��H��H�5�H��H��@(�~��H���H�5�H��H��@(7�~��H���H�5�H��H��@("�i~��H���H�5�H��H��@(�I~��H���H�5�H��H��@($�)~��H�r�H�5�H��H��@(#�	~��H�R�H�5rH��H��@(%��}��H�2�H�5cH��H��@(&��}��H��H�5OH��H��@()�}��H���H�5;H��H��@(�}��H���H�5'H��H��@(�i}��H�r���H�5H��H��@(�I}��H����H�5H���3}��H�|��H�5H���}��H�����H�5H���}��H�����H�5�H��H��@(������|��H�p���H�5�H��H��@(���|��H�P���H�5�H��H��@(�|��H�0���H�5�H��H��@(�|��H����H�5�H��H��@(�g|��H����H�5�H��H��@(��G|��H�P���H�5�H���1|��H����H�5�H���|��H����H�5xH��H��@(	�{��H����H�5fH��H��@( ��{��H����H�5UH��H��@(\�{��H�d��H�5AH��H��@(@�{��H�D��H�50H��H��@(P�{{��H�$��H�5#H��H��@(X�[{��H���H�5H��H��@( �;{��H����H�5�H��H��@(�{��H����H�5�H��H��@((�z��H����H�5�H��H��@(��z��H����H�5�H��H��@(�z��H�d��H�5�H��H��@(x�z��H�D��H�5�H��H��@(p�{z��H�$��H�5�H��H��@(h�[z��H���H�5�H��H��@(`�;z��H����H�5tH��H��@(��z��H����H�5bH��H��@(��y��H����H�5OH��H��@( ��y��H����H�5AH��H��@(H�y��H�d��H�5-H��H��@(8�y��H�D��H�5H��H��@(@�{y��H�$��H�5H��H��@(X�[y��H���H�5�H��H��@(P�;y��H����H�5�H��H��@( �y��H����H�5�H��H��@( �x��H����H�5�H��H��@((��x��H����H�5�H��H��@(�x��H�d��H�5�H��H��@(�x��H�D��H�5�H��H��@(@�{x��H�$��H�5qH��H��@(8�[x��H���H�5bH��H��@(0�;x��H����H�5PH��H��@(H�x��H�t��H�5AH��H��@(�w��H�T��H�54H��H��@(��w��H����H�5"H��H��@(�w��H����H�5H���w��H���H�5H��H��@(�w��H�Χ��H�5�H��H��@(�ew��H�����H�5�H��H��@(�Ew��H�����H�5�H��H��@(�%w��H���H�5�H���w��H�ؾ��H�5�H��H��@(��v��H�����H�5�H��H��@(��v��H�����H�5�H��H��@(�v��H�X���H�5�H��H��@(�v��H�����H�5uH���yv��H�����H�5oH��H��@(�Yv��H�r���H�5`H��H��@(�9v��H�R���H�5TH��H��@(�v��H�2���H�5BH��H��@(�u��H����H�54H��H��@(��u��H��H�5"H��H��@(�u��H�Һ��H�5H��H��@(�u��H�����H�5H��H��@(�yu��H�‰��H�5�H��H��@(�Yu��H�Ҋ��H�5�H���Cu��H�����H�5�H���-u��H���H�5�H��H��@(�
u��H�ƕ��H�5�H��H��@(��t��H�F��H�5�H��H��@(��t��H�&��H�5�H��H��@(�t��H�v���H�5�H��H��@(�t��H�F���H�5uH���wt��H�0���H�5iH��H��@((�Wt��H����H�5SH��H��@(�7t��H��H�5@H��H��@(�t��H�з��H�5+H��H��@(8�s��H�����H�5H��H��@(0��s��H�����H�5H��H��@(�s��H�p���H�5�H��H��@( �s��H�P���H�5�H��H��@(�ws��H�����H�5�H��H��@(�Ws��H� ���H�5�H���As��H�*���H�5�H���+s��H�d���H�5�H���s��H�����H�5�H���r��H�X���H�5�H����r��H�"���H�5�H����r��H�l���H�5�H���r��H�F���H�5wH���r��H�`���H�5nH���r��H�J���H�5dH��H��@(�qr��H�ʘ��H�5QH��H��@(�Qr��H��{��H�5>H���;r��H����H�57H���%r��H�ސ��H�5.H���r��H�Ȑ��H�5$H��H��@(��q��H�����H�5H��H��@(��q��H�����H�5H���q��H�����H�5�H���q��H����H�5�H���q��H�ƥ��H�5�H���wq��H�����H�5�H���aq��H�����H�5�H���Kq��H�����H�5�H��H��@(�+q��H�t���H�5�H��H��@(�q��H�t���H�5�H���p��H����H�5�H����p��H�����H�5�H��H��@(�p��H��x��H�5�H��H��@(�p��H�8���H�5�H���p��H�����H�5|H���sp��H��~��H�5{H���]p��H�v���H�5xH���Gp��H�w��H�5xH���1p��H����H�5{H���p��H����H�5tH��H��@(�o��H���H�5�*H��H��@(��o��H�đ��H�5FH��H��@(�o��H�����H�5DH��H��@(�o��H�����H�54H��H��@((�{o��H�d���H�5)H��H��@(�[o��H�D���H�5H��H��@( �;o��H�$���H�5
H��H��@(�o��H���H�5H��H��@( �n��H��{��H�5�H����n��H��o �8�n���H�5�H��H���p��H�5��H��I���o��H�����I���f.�I�t$H��I����o��A�L$�L��H��I�T$�I�����H��H�p�k��L��H��H���m��I�<$u���L�%*D �
�I�t$H��I���n��A�L$�L��H��I�T$�I�����H��H�p�Kk��L��H��H���Mm��I�<$u�L��H��H��h��k��H�ߺ@H�55o �0k��H��8H��H�
�H�PH��PH�5�H�hH�PH��q��H�H�@ H�@(H�@0�Zm��H��H�
�H��q��H�H�5��@(p�3m��H��H�
bH�bq��H�H�5m�@(��m��H��H�
;H�;q��H�H�5V�@(���l��H��H�
H�q��H�H�5;�@(�l��H��H�
�H��p��H�H�5�@(X�l��H��H�
�H��p��H�H�5�@(��pl��H��H�
�H��p��H�H�5��@(0�Il��H��H�
xH�xp��H�H�5��@(��"l��H��H�
QH�Qp��H�H�5��@(��k��H��H�
*H�*p��H�H�5��@(0��k��H�
H��H�p��H�H�5|�@(X�k��H�ߺH�5lH��@(P�ok��H��H�߹H���k��H��A�	��H�5A�
k��A�	H�߹�H�5$H����j��H��H�߹H���hk��A�	H�߹�H�5�j��H��H�߹H���6k��H��A�	��H�5��j��A�	H�߹�H�5�H���ej��H��H�߹H����j��H��A�	��H�5�3j��A�	H�߹�H�5�H���j��H��H�߹H���j��H��A�	��H�5$%��i��H��A�	�� H�5%%H���i��H��H��H���:j��H��D��H��[]A\A]A^A_�h����H��H���B::SPECIALB::MAGICB::PADLISTB::NULLB::PADNAMEpnl, idxpnl is not a referenceB::PADNAMELISTpadlist is not a referencecv is not a referencegv is not a referencesv is not a referenceargument is not SvROKargument is not a referencepnpn is not a referencehehe is not a referencepnlpadlist, idxformatformat is not a referenceih is not a referencehvhv is not a referenceav, idxav is not a referenceio, namestdinio is not a referencestdoutstderrInvalid value '%s'???NULL gp in B::GV::%smgmg is not a referenceo, cv%ld,%ld,%c\'\\\n\r\t\a\b\f\v\%03o\"\$\@nrftax\opnumpp_%spp_op, methodop is not a reference0x%lxB::overlayPL_ppaddr[OP_%s]B::RHEmethod %s not implemented1.68v5.26.0B.cB::formfeedB::amagic_generationB::comppadlistB::sv_noB::sv_undefB::sv_yesB::main_rootB::main_startB::dowarnB::sub_generationB::walkoptreeB::walkoptree_debugB::addressB::svref_2objectB::opnumberB::ppnameB::hashB::cast_I32B::minus_cB::save_BEGINsB::ccharB::cstringB::perlstringB::threadsv_namesB::CLONEB::BINOP::lastB::COP::arybaseB::COP::cop_seqB::COP::fileB::COP::filegvB::COP::hintsB::COP::hints_hashB::COP::ioB::COP::labelB::COP::lineB::COP::stashB::COP::stashoffB::COP::stashpvB::COP::warningsB::LISTOP::childrenB::LOGOP::otherB::LOOP::lastopB::LOOP::nextopB::LOOP::redoopB::METHOP::firstB::METHOP::meth_svB::METHOP::rclassB::OP::descB::OP::flagsB::OP::foldedB::OP::moresibB::OP::nameB::OP::nextB::OP::optB::OP::parentB::OP::ppaddrB::OP::privateB::OP::savefreeB::OP::siblingB::OP::sizeB::OP::slabbedB::OP::spareB::OP::staticB::OP::targB::OP::typeB::PADOP::gvB::PADOP::padixB::PADOP::svB::PMOP::code_listB::PMOP::pmflagsB::PMOP::pmoffsetB::PMOP::pmregexpB::PMOP::pmreplrootB::PMOP::pmreplstartB::PMOP::pmstashB::PMOP::pmstashpvB::PMOP::precompB::PMOP::reflagsB::PVOP::pvB::SVOP::gvB::SVOP::svB::UNOP::firstB::OP::oplistB::UNOP_AUX::stringB::UNOP_AUX::aux_listB::SV::FLAGSB::SV::MAGICALB::SV::POKB::SV::REFCNTB::SV::ROKB::SV::SvTYPEB::SV::object_2svrefB::IV::IVB::AV::MAXB::BM::USEFULB::CV::CvFLAGSB::CV::FILEB::CV::OUTSIDEB::CV::OUTSIDE_SEQB::CV::STASHB::GV::GvFLAGSB::GV::STASHB::HV::KEYSB::HV::MAXB::IO::BOTTOM_GVB::IO::BOTTOM_NAMEB::IO::FMT_GVB::IO::FMT_NAMEB::IO::IoFLAGSB::IO::IoTYPEB::IO::LINESB::IO::LINES_LEFTB::IO::PAGEB::IO::PAGE_LENB::IO::TOP_GVB::IO::TOP_NAMEB::IV::IVXB::IV::UVXB::NV::NVXB::PV::CURB::PV::LENB::PVLV::TARGB::PVLV::TARGLENB::PVLV::TARGOFFB::PVLV::TYPEB::PVMG::SvSTASHB::IV::needs64bitsB::IV::packivB::NV::NVB::REGEXP::REGEXB::REGEXP::compflagsB::REGEXP::precompB::REGEXP::qr_anoncvB::PV::RVB::BM::TABLEB::PV::PVB::PV::PVBMB::PV::PVXB::PVMG::MAGICB::MAGIC::FLAGSB::MAGIC::LENGTHB::MAGIC::MOREMAGICB::MAGIC::OBJB::MAGIC::PRIVATEB::MAGIC::PTRB::MAGIC::REGEXB::MAGIC::TYPEB::MAGIC::precompB::BM::PREVIOUSB::BM::RAREB::GV::FILEB::GV::NAMEB::HV::NAMEB::GV::isGV_with_GPB::GV::is_emptyB::GV::GPB::GV::AVB::GV::CVB::GV::CVGENB::GV::EGVB::GV::FORMB::GV::GvREFCNTB::GV::HVB::GV::IOB::GV::SVB::GV::LINEB::GV::GPFLAGSB::GV::FILEGVB::IO::IsSTDB::AV::FILLB::AV::ARRAYB::AV::ARRAYeltB::FM::LINESB::CV::CONSTB::CV::ROOTB::CV::STARTB::CV::DEPTHB::CV::PADLISTB::CV::HSCXTB::CV::XSUBB::CV::XSUBANYB::CV::const_svB::CV::GVB::CV::NAME_HEKB::HV::FILLB::HV::RITERB::HV::ARRAYB::HE::SVKEY_forceB::HE::VALB::HE::HASHB::RHE::HASHB::PADLIST::MAXB::PADNAMELIST::MAXB::PADLIST::NAMESB::PADLIST::ARRAYB::PADLIST::ARRAYeltB::PADLIST::REFCNTB::PADNAMELIST::ARRAYB::PADNAMELIST::ARRAYeltB::PADLIST::idB::PADLIST::outidB::PADNAME::COP_SEQ_RANGE_LOWB::PADNAME::LENB::PADNAME::OURSTASHB::PADNAME::REFCNTB::PADNAME::TYPEB::PADNAMELIST::REFCNTB::PADNAME::PVB::PADNAME::FLAGSB::B::EXPORT_OKB.xsB::init_avB::check_avB::unitcheck_avB::begin_avB::end_avB::main_cvB::inc_gvB::defstashB::curstashB::regex_padavB::warnhookB::diehookB::OP::does_parentB::PADNAME::SvSTASHB::PADNAME::PROTOCVB::PADNAME::PVXB::PADNAME::PARENT_PAD_INDEXSVTYPEMASKSVt_PVGVSVt_PVHVPAD_FAKELEX_ANONPAD_FAKELEX_MULTISVpad_STATESVpad_TYPEDSVpad_OURCXTYPEMASKCXt_NULLCXt_WHENCXt_BLOCKCXt_GIVENCXt_LOOP_ARYCXt_LOOP_LAZYSVCXt_LOOP_LAZYIVCXt_LOOP_LISTCXt_LOOP_PLAINCXt_SUBCXt_FORMATCXt_EVALCXt_SUBSTCXp_MULTICALLCXp_HASARGSCXp_SUB_RECXp_SUB_RE_FAKECXp_REALCXp_TRYBLOCKCXp_FOR_DEFCXp_FOR_LVREFCXp_FOR_GVCXp_FOR_PADCXp_ONCEG_SCALARG_ARRAYG_VOIDG_WANTG_DISCARDG_EVALG_NOARGSG_KEEPERRG_NODEBUGG_METHODG_FAKINGEVALG_UNDEF_FILLG_WRITING_TO_STDERRG_RE_REPARSINGG_METHOD_NAMEDEVAL_NULLEVAL_INEVALEVAL_WARNONLYEVAL_KEEPERREVAL_INREQUIREPERLSI_UNDEFPERLSI_MAINPERLSI_MAGICPERLSI_SORTPERLSI_SIGNALPERLSI_OVERLOADPERLSI_DESTROYPERLSI_WARNHOOKPERLSI_DIEHOOKPERLSI_REQUIREPERLSI_MULTICALLCVf_METHODCVf_LVALUECVf_CONSTCVf_ISXSUBCVf_WEAKOUTSIDECVf_CLONECVf_CLONEDCVf_ANONCVf_UNIQUECVf_NODEBUGCVf_CVGV_RCCVf_DYNFILECVf_AUTOLOADCVf_HASEVALCVf_NAMEDCVf_LEXICALCVf_ANONCONSTGVf_INTROGVf_MULTIGVf_ASSUMECVGVf_IMPORTEDGVf_IMPORTED_SVGVf_IMPORTED_AVGVf_IMPORTED_HVGVf_IMPORTED_CVOPf_WANTOPf_WANT_VOIDOPf_WANT_SCALAROPf_WANT_LISTOPf_KIDSOPf_PARENSOPf_REFOPf_MODOPf_STACKEDOPf_SPECIALOPf_FOLDEDPMf_HAS_ERRORPMf_RETAINTPMf_ONCEPMf_USEDPMf_CONSTPMf_KEEPPMf_GLOBALPMf_CONTINUEPMf_EVALPMf_NONDESTRUCTPMf_HAS_CVPMf_CODELIST_PRIVATEPMf_IS_QRPMf_USE_RE_EVALOA_MARKOA_FOLDCONSTOA_RETSCALAROA_TARGETOA_TARGLEXOA_OTHERINTOA_DANGEROUSOA_DEFGVOCSHIFTOA_CLASS_MASKOA_BASEOPOA_UNOPOA_BINOPOA_LOGOPOA_LISTOPOA_PMOPOA_SVOPOA_PADOPOA_PVOP_OR_SVOPOA_LOOPOA_COPOA_BASEOP_OR_UNOPOA_FILESTATOPOA_LOOPEXOPOA_METHOPOA_UNOP_AUXOASHIFTOA_SCALAROA_LISTOA_AVREFOA_HVREFOA_CVREFOA_FILEREFOA_SCALARREFOA_OPTIONALPERL_LOADMOD_DENYPERL_LOADMOD_NOIMPORTPERL_LOADMOD_IMPORT_OPSBHKf_bhk_startBHKf_bhk_pre_endBHKf_bhk_post_endBHKf_bhk_evalRV2CVOPCV_MARK_EARLYRV2CVOPCV_RETURN_NAME_GVRV2CVOPCV_RETURN_STUBRV2CVOPCV_FLAG_MASKOP_LVALUE_NO_CROAKXOPf_xop_nameXOPf_xop_descXOPf_xop_classXOPf_xop_peepMDEREF_reloadMDEREF_AV_pop_rv2av_aelemMDEREF_AV_vivify_rv2av_aelemMDEREF_AV_padav_aelemMDEREF_AV_gvav_aelemMDEREF_HV_pop_rv2hv_helemMDEREF_HV_vivify_rv2hv_helemMDEREF_HV_padhv_helemMDEREF_HV_gvhv_helemMDEREF_ACTION_MASKMDEREF_INDEX_noneMDEREF_INDEX_constMDEREF_INDEX_padsvMDEREF_INDEX_gvsvMDEREF_INDEX_MASKMDEREF_FLAG_lastMDEREF_MASKMDEREF_SHIFTOPpARGELEM_SVOPpLVREF_SVOPpARG1_MASKOPpCOREARGS_DEREF1OPpENTERSUB_INARGSOPpSORT_NUMERICOPpTRANS_FROM_UTFOPpARGELEM_AVOPpCONST_NOVEROPpCOREARGS_DEREF2OPpEVAL_HAS_HHOPpFT_ACCESSOPpHINT_STRICT_REFSOPpITER_REVERSEDOPpSORT_INTEGEROPpTRANS_TO_UTFOPpARG2_MASKOPpAVHVSWITCH_MASKOPpARGELEM_HVOPpCONST_SHORTCIRCUITOPpDONT_INIT_GVOPpENTERSUB_HASTARGOPpEVAL_UNICODEOPpFT_STACKEDOPpLVREF_ELEMOPpSLICEWARNINGOPpSORT_REVERSEOPpSPLIT_IMPLIMOPpTRANS_IDENTICALOPpARGELEM_MASKOPpARG3_MASKOPpPADRANGE_COUNTSHIFTOPpCONST_STRICTOPpENTERSUB_AMPEROPpEVAL_BYTESOPpFT_STACKINGOPpITER_DEFOPpLVREF_ITEROPpMAYBE_LVSUBOPpREVERSE_INPLACEOPpSORT_INPLACEOPpSPLIT_LEXOPpTRANS_SQUASHOPpARG4_MASKOPpASSIGN_COMMON_AGGOPpCONST_ENTEREDOPpDEREF_AVOPpEVAL_COPHHOPpFT_AFTER_tOPpLVREF_AVOPpMAYBE_TRUEBOOLOPpMULTIDEREF_EXISTSOPpOPEN_IN_RAWOPpSORT_DESCENDOPpSPLIT_ASSIGNOPpSUBSTR_REPL_FIRSTOPpTARGET_MYOPpASSIGN_COMMON_RC1OPpDEREF_HVOPpEARLY_CVOPpEVAL_RE_REPARSINGOPpHUSH_VMSISHOPpLVREF_HVOPpMAY_RETURN_CONSTANTOPpMULTIDEREF_DELETEOPpOPEN_IN_CRLFOPpSORT_QSORTOPpTRANS_COMPLEMENTOPpTRUEBOOLOPpDEREFOPpDEREF_SVOPpLVREF_CVOPpLVREF_TYPEOPpALLOW_FAKEOPpASSIGN_BACKWARDSOPpASSIGN_COMMON_SCALAROPpCONST_BAREOPpCOREARGS_SCALARMODOPpENTERSUB_DBOPpEXISTS_SUBOPpFLIP_LINENUMOPpLIST_GUESSEDOPpLVAL_DEFEROPpOPEN_OUT_RAWOPpOUR_INTROOPpPAD_STATEOPpREFCOUNTEDOPpREPEAT_DOLISTOPpSLICEOPpSORT_STABLEOPpTRANS_GROWSOPpPADRANGE_COUNTMASKOPpASSIGN_CV_TO_GVOPpCOREARGS_PUSHMARKOPpENTERSUB_NOPARENOPpLVALUEOPpLVAL_INTROOPpOFFBYONEOPpOPEN_OUT_CRLFOPpPV_IS_UTF8OPpTRANS_DELETERXf_PMf_STD_PMMOD_SHIFTRXf_PMf_MULTILINERXf_PMf_SINGLELINERXf_PMf_FOLDRXf_PMf_EXTENDEDRXf_PMf_EXTENDED_MORERXf_PMf_NOCAPTURERXf_PMf_KEEPCOPYRXf_PMf_CHARSETRXf_PMf_STRICTRXf_PMf_SPLITPADNAMEt_OUTERPADNAMEt_STATEPADNAMEt_LVALUEPADNAMEt_TYPEDPADNAMEt_OURRXf_NO_INPLACE_SUBSTRXf_EVAL_SEENRXf_UNBOUNDED_QUANTIFIER_SEENRXf_CHECK_ALLRXf_MATCH_UTF8RXf_USE_INTUIT_NOMLRXf_USE_INTUIT_MLRXf_INTUIT_TAILRXf_IS_ANCHOREDRXf_COPY_DONERXf_TAINTED_SEENRXf_TAINTEDRXf_START_ONLYRXf_SKIPWHITERXf_WHITERXf_NULLSVf_IOKSVf_NOKSVf_POKSVf_ROKSVp_IOKSVp_NOKSVp_POKSVp_SCREAMSVf_PROTECTSVs_PADTMPSVs_PADSTALESVs_TEMPSVs_OBJECTSVs_GMGSVs_SMGSVs_RMGSVf_FAKESVf_OOKSVf_BREAKSVf_READONLYSVf_AMAGICSVf_IsCOWSVf_UTF8SVf_IVisUVSVs_PADMYHEf_SVKEYB::OPB::UNOPB::BINOPB::LOGOPB::LISTOPB::PMOPB::SVOPB::PADOPB::PVOPB::LOOPB::COPB::METHOPB::UNOP_AUXB::IVB::NVB::PVB::INVLISTB::PVIVB::PVNVB::PVMGB::REGEXPB::GVB::PVLVB::AVB::HVB::CVB::FMB::IOIllegal alias 0x%08x for B::*SVREGEX is only meaningful on r-magicprecomp is only meaningful on r-magicargument to B::BM::TABLE is not a PVBMIllegal alias 0x%08x for B::*IVXCouldn't add key '%s' to %%B::Illegal alias %d for B::*OP::nextIllegal type 0x%x for B::*OP::%sB::PADNAME::COP_SEQ_RANGE_HIGHB::PADNAME::PARENT_FAKELEX_FLAGSMDEREF_AV_gvsv_vivify_rv2av_aelemMDEREF_AV_padsv_vivify_rv2av_aelemMDEREF_HV_gvsv_vivify_rv2hv_helemMDEREF_HV_padsv_vivify_rv2hv_helem����Њ����� ���0���@���X������@���ԑ������t���t�������������<�������̑����l���L���������L���������Y�����������������������#������������ԭ������������������p���\���H���4��� ������������������������������������~���s���`�������������� ���0���@��������4����������������������������������������������������������������������������������������������������ش��ش��@���������������-�����������������������N���ų����������S���������������������u���N�������(0888`000PP88;�S@9����>����C����D���D��`E��,�E��hpF���G����G����G���H��XJ���K��� L��@M��TN����N����O���Q��$PR��`�S����T���V��@W��PPW��d�X����Y����Z�� `\��lp^����_����`��$	�a��`	�b���	�c���	�d���	�f��`
 h���
`i���
�j���k��P0m���Pn���@o��0p��Dq��tr���t��
v��D
@w���
�x���
py���
0z���z��DP{��t�|����}��~��< ����������������T������������$����` ����p����@������D`����p��� ���8 ���� ����`��� `���lp����p����P���<���p`���zRx�$x6��PFJw�?:*3$"D�;��@\�A��:kp�A��sd8�,B���B�B�D �D(�F0]
(D ABBH,��B��sF�A�A �[
ABA(��B���E�A�G f
AAA( 4C���E�A�G e
AAA(L�C��:B�D�A �oAB8x�C���F�B�A �A(�G0�
(A ABBC<�0D��lF�B�B �A(�A0��
(A BBBB<�`E���F�B�B �A(�A0��
(A BBBG<4 F��F�B�B �A(�A0��
(A BBBD8tG��F�A�D ��
ABKf
ABG(��G���E�A�J s
AAK(��H���E�A�J S
AAA8�H��GF�B�A �A(�J0�
(A ABBH8D�I��'F�B�A �A(�G0�
(A ABBB8��J��7F�B�A �A(�J0�
(A ABBG8��K��7F�B�A �A(�J0�
(A ABBD8��L��?F�B�A �A(�J0�
(A ABBG84�M��?F�B�A �A(�J0�
(A ABBH8p�N��$F�B�A �A(�G0�
(A ABBB��O��	<��O��?F�B�B �A(�A0��
(A BBBD8�P���F�B�A �A(�J0�
(A ABBG<<�Q��BF�B�B �A(�A0��
(A BBBDH|�R��rF�B�B �B(�A0�A8�JP�
8A0A(B BBBIH��S��
F�B�B �B(�G0�A8�DP>
8A0A(B BBBH8�U��F�B�G �A(�D0�
(A ABBF,P�V���F�A�A ��
ABK8�TW��F�B�A �A(�G0�
(A ABBH,�8X���F�A�A ��
ABE,��X��'F�A�A ��
ABC8�Y��F�B�A �A(�G0�
(A ABBJ`X�Z��
F�B�B �D(�A0��
(A BBBFq
(A BBBHl
(A BBBM8�x\��7F�B�A �A(�J0�
(A ABBJ8�|]��:F�B�A �A(�G0�
(A ABBI84�^��$F�B�A �A(�G0�
(A ABBB8pt_��2F�B�A �A(�G0�
(A ABBD8�x`��ZF�B�A �A(�J0�
(A ABBA8��a��F�B�A �A(�J0�
(A ABBI<$	�b���F�B�B �A(�A0��
(A BBBI8d	0c���F�B�A �A(�J0�
(A ABBG,�	�c���F�A�A ��
ABC,�	�d��F�A�A ��
ABI`
de���F�B�B �A(�A0��
(A BBBE^
(A BBBCs
(A BBBF8d
g���F�B�A �G(�D0�
(A ABBJ8�
�h��:F�B�A �A(�G0�
(A ABBA8�
�i��MF�B�A �A(�G0�
(A ABBH,�j���F�A�A ��
ABH(H|k���E�A�J q
AAE(tl��KB�D�A �@AB,�4l���F�A�A ��
ABJ8��l��{B�B�A �D(�D0�
(D ABBIzRx�0����$�4��
(@�m���E�A�J l
AAB(lhn��xE�A�J Y
AAAL��n��F�B�B �A(�A0��
(A BBBJ�
(A BBBIH��p���F�B�B �B(�A0�G8�DP�
8A0A(B BBBF84
�q��OF�B�A �A(�J0�
(A ABBE<p
�r���F�B�B �A(�A0�
(A BBBB(�
Tt���E�A�J �
AAI<�
�t��\F�E�B �A(�A0��
(A BBBA`v���F�B�B �A(�A0��
(A BBBDM
(A BBBD[
(A BBBF8�dx��F�B�A �A(�J0O
(A ABBG8�Hz��jF�B�A �A(�G0�
(A ABBG8�|{��LF�B�A �A(�G@�
(A ABBJ84�|���F�B�A �A(�G0�
(A ABBI,p$~���F�A�A ��
ABF���~��FF�B�B �B(�A0�A8�Gp�
8A0A(B BBBCm
8A0A(B BBBI
8A0A(B BBBAt
8A0A(B BBBB<8|���F�B�B �A(�A0��
(A BBBFxL����L��H����F�B�B �B(�A0�A8�JP�
8A0A(B BBBBL������F�B�B �A(�A0�z
(A BBBCL
(A BBBAH0D���8F�B�B �E(�A0�A8�DP�
8A0A(B BBBEH|8����F�B�B �B(�A0�A8�GP�
8A0A(B BBBJH���B�E�B �B(�A0�D8�GP�
8D0A(B BBBI,�����F�A�A ��
ABBPD�����B�N�B �E(�D0�D8�DHBPFHA@I
8D0A(B BBBF0�����F�A�A �J0�
 AABH������DF�B�B �B(�A0�A8�Gp�xH�J�B�VpExH�QxAp`
8A0A(B BBBE{
8A0A(B BBBC�xG�VxApH`T���oF�N�P �B(�H0�A8�L@8G0A(B BBBGNU�`Q Q`$!��
���	����������	�
#�,�5�	?�	I�V�f�v�
����	��

����	��
� �
@��� ��@��
 �
@)��5�>�G�O�V�]�	g�n�w�	 ��	@������������	���
��� �-�9�F�R�
`�p������	��
��
�
�	�
���	 �
@���
"�.�:�F� S�@_�	�i�u�
��	��	��������� �@�����
��
&�/�
:�B� J�@V��b�
m�
{����� ��	@�����
�����
� ��	@����,�9�	C�
N� Z�@g��p�x�
��	��������	�������	�
���
�
�	"�.�6�	@�H�Q�Z�c�
n�{������������
��5�K�_�r�
��
����
��
���	!�	"����
!	0
"
5�R�h�
}������� �0�0�@��	��
$�0�=�P�c�s���
�������������#�6�
D�Z�j�~���
��
���������
!1C
Q`l
z��������

$0BWfv��� � � � � �   1 A
 O c o0x0�0�
0�
@�@�@�
@�@�@
@@)@9
@G@W@d@q
@@�@�@�@�������		�
�!�-�>
�L�\t����� �@��
x
�����
 �@��
	,;KZg|
��
�� �@���
*6E
 S	@]�fnv~�� �@�
���
���
� �@���
	!
,	6 ?
�J	T	������������&�Y�"��#�(��0��0��	�8��@��H}�@j�	X^�(A�(N�(�<w�$=�8��8.�!�0������(��h�M���2��������
��	����^�A�!�i����^�K�
�����f�t����,���?���^dlu~�����������������
!'-3U!�E
��P$!X$!���o`��
Y�L!�>8�*	���o���o����o�o"���o��J! F0F@FPF`FpF�F�F�F�F�F�F�F�FGG G0G@GPG`GpG�G�G�G�G�G�G�G�GHH H0H@HPH`HpH�H�H�H�H�H�H�H�HII I0I@IPI`IpI�I�I�I�I�I�I�I�IJJ J0J@JPJ`JpJ�J�J�J�J�J�J�J�JKK K0K@KPK����GA$3a1�E��GA$3p1113�P��GA*GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobinGA$running gcc 8.5.0 20210514GA*GA*GA!
GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GOW*�GA*cf_protectionGA+omit_frame_pointerGA+stack_clashGA!stack_realign
GA*FORTIFYpQ��GA+GLIBCXX_ASSERTIONSB.so-5.26.3-423.el8_10.x86_64.debug�Om�7zXZ�ִF!t/���]?�E�h=��ڊ�2N�I�� ��X���~X�o��/���������k���q�KLQy��
v���
#����
*t�Ξ�&���r�Um�Sh�2\�ž"��҆�/h��c�v���ܹ��mSG:��p#�lN��{���*��ahW�Ƚ]�o]�[{?dqOOA�j\@#/�dQzu?�J�V�)Q�'z�U�5):���+
8�r��J�&8���P�p�zB�{����P����jX6�=7@Aq��M
f��KF;��;"l�~k�*[�Q�/�U�
8��fN����A.r	z*�=f�����j��ݯ0��kJ�%�Q���_R7��2��6^^�����@/�=�aiT�⾀��%�N�{6|g��;�3#��ƝZ���1��e��!�4�P�/����?#j�}K�j�ne=�>�R�Ko���V4dsg�ۏ�Du���-%�F�������lK�<Ŗ��I�{�,��F�$?��	Μ����Zb�Hh�y��M㥸�!oRD'��$",��
>P����?��Z�8G&V�x{X���h�pjC�W��@�����mo>���ak����ʆ?�^Yq��	d3I`Mfi�9�rOmH���⺗M����O�0g'v�0";�'�'#��2ozA�6���%R�d��Nɀ�ٖ�'b�W�k�&lK+��~R�*v��z?��v8��2���Z�Ep��%B��	�K_�����9Sܧ��$ge���$�`oA�o�o5���ץ!0������Ͷ�)�����}�q��Ҍ�aEaY�3>�ɦ�<������0��o�����#�q��>
y��v�k �R��2�d�E����o�`�B��P����E�Cl6%�6l�e��{j1�>w�"�C���>EZI��ƇM�%Q�99��W��qC!XR�`+�<q=��٢��QH����ۡ����K��ȱ�(�/�\g���1Zw���~��Qa��ٵѦ��>N<*wi`�!��uUt�?8���%Q�p�LB���	"�RD�WRA&T��1�3A�"��\���G��qHȌ�ۺ����YM���JENN��+��F�5i�������+�դ�Jʷ���&���f��i�[�Sv7�͹�q%}��mG��tF4EP��21&<�r�+�b���g�ɥ{E�{�T ��*�d�g<t�	נXpwt^����;+�(3���	<S+�.��y��m*
F�矨	��!0A�Řm�
aFp,>!(�:W'�Gr��p�*CܑSV]�Eס�A��0����R���o���;HX�y�#=l���k�W
Q�1�I��;�;5F�{�H�
TV8t�/-��j���ۂ�/�4�3��;��z�a�%Tx{�95;��!��%}�C�������wM�/Y���k�Ā�|:G>D�����#%�hӛ��v��(�rŽ���Ê�[��h��P��ᮊE�݀s�i��G��eZ��'��;�l�X��ٰK�a�Ne��� �Y�p*��J����hqE��#���+��|���8���3��7��O���nF/�84�
�;=������_Iѓb��Ǖ�y<���a�(�B���ح���(�	BU��t�N�0:�FLs�P�FND�?y0$���<�Iq�d	��}}���'�o���9t5q��w���&�x�cf���a���Ҋf�e���Hc�
�7�,�
�5��d��g�YZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata88$���o``4(��0	0��Y8���o""�E���o��PT88�*^B>>�h�E�EcFFPn`K`K@w�P�P��}����
�����( �����xx��(#(# �P$!P$�X$!X$�`$!`$�& ��J!�J��L!�L�P!P�P!P�PaPH
LR(tR|Y(Deparse.pm000064400000600300151004206260006460 0ustar00# B::Deparse.pm
# Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 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;
use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
	 OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
	 OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL OPf_MOD OPf_PARENS
	 OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
	 OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY
	 OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER OPpREPEAT_DOLIST
	 OPpSORT_REVERSE OPpMULTIDEREF_EXISTS OPpMULTIDEREF_DELETE
         OPpSPLIT_ASSIGN OPpSPLIT_LEX
	 SVf_IOK SVf_NOK SVf_ROK SVf_POK SVpad_OUR SVf_FAKE SVs_RMG SVs_SMG
	 SVs_PADTMP SVpad_TYPED
         CVf_METHOD CVf_LVALUE
	 PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE
	 PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED PMf_EXTENDED_MORE
	 PADNAMEt_OUTER
        MDEREF_reload
        MDEREF_AV_pop_rv2av_aelem
        MDEREF_AV_gvsv_vivify_rv2av_aelem
        MDEREF_AV_padsv_vivify_rv2av_aelem
        MDEREF_AV_vivify_rv2av_aelem
        MDEREF_AV_padav_aelem
        MDEREF_AV_gvav_aelem
        MDEREF_HV_pop_rv2hv_helem
        MDEREF_HV_gvsv_vivify_rv2hv_helem
        MDEREF_HV_padsv_vivify_rv2hv_helem
        MDEREF_HV_vivify_rv2hv_helem
        MDEREF_HV_padhv_helem
        MDEREF_HV_gvhv_helem
        MDEREF_ACTION_MASK
        MDEREF_INDEX_none
        MDEREF_INDEX_const
        MDEREF_INDEX_padsv
        MDEREF_INDEX_gvsv
        MDEREF_INDEX_MASK
        MDEREF_FLAG_last
        MDEREF_MASK
        MDEREF_SHIFT
    );

$VERSION = '1.40';
use strict;
use vars qw/$AUTOLOAD/;
use warnings ();
require feature;

BEGIN {
    # List version-specific constants here.
    # Easiest way to keep this code portable between version looks to
    # be to fake up a dummy constant that will never actually be true.
    foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED OPpCONST_NOVER
		OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
		PMf_CHARSET PMf_KEEPCOPY PMf_NOCAPTURE CVf_ANONCONST
		CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
		PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES
		OPpLVREF_TYPE OPpLVREF_SV OPpLVREF_AV OPpLVREF_HV
		OPpLVREF_CV OPpLVREF_ELEM SVpad_STATE)) {
	eval { B->import($_) };
	no strict 'refs';
	*{$_} = sub () {0} unless *{$_}{CODE};
    }
}

# Changes between 0.50 and 0.51:
# - fixed nulled leave with live enter in sort { }
# - fixed reference constants (\"str")
# - handle empty programs gracefully
# - handle infinite 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_5005THREADS)
# - 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 attributes was added
# - some warnings fixed
# - separate recognition of constant subs
# - rewrote continue block handling, now recognizing for loops
# - added more control of expanding control structures
# Changes between 0.60 and 0.61 (mostly by Robin Houston)
# - many bug-fixes
# - support for pragmas and 'use'
# - support for the little-used $[ variable
# - support for __DATA__ sections
# - UTF8 support
# - BEGIN, CHECK, INIT and END blocks
# - scoping of subroutine declarations fixed
# - compile-time output from the input program can be suppressed, so that the
#   output is just the deparsed code. (a change to O.pm in fact)
# - our() declarations
# - *all* the known bugs are now listed in the BUGS section
# - comprehensive test mechanism (TEST -deparse)
# Changes between 0.62 and 0.63 (mostly by Rafael Garcia-Suarez)
# - bug-fixes
# - new switch -P
# - support for command-line switches (-l, -0, etc.)
# Changes between 0.63 and 0.64
# - support for //, CHECK blocks, and assertions
# - improved handling of foreach loops and lexicals
# - option to use Data::Dumper for constants
# - more bug fixes
# - discovered lots more bugs not yet fixed
#
# ...
#
# Changes between 0.72 and 0.73
# - support new switch constructs

# Todo:
#  (See also BUGS section at the end of this file)
#
# - finish tr/// changes
# - add option for even more parens (generalize \&foo change)
# - left/right context
# - 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'?
# - version using op_next instead of op_first/sibling?
# - avoid string copies (pass arrays, one big join?)
# - here-docs?

# Current test.deparse failures
# comp/hints 6 - location of BEGIN blocks wrt. block openings
# run/switchI 1 - missing -I switches entirely
#    perl -Ifoo -e 'print @INC'
# op/caller 2 - warning mask propagates backwards before warnings::register
#    'use warnings; BEGIN {${^WARNING_BITS} eq "U"x12;} use warnings::register'
# op/getpid 2 - can't assign to shared my() declaration (threads only)
#    'my $x : shared = 5'
# op/override 7 - parens on overridden require change v-string interpretation
#    'BEGIN{*CORE::GLOBAL::require=sub {}} require v5.6'
#    c.f. 'BEGIN { *f = sub {0} }; f 2'
# op/pat 774 - losing Unicode-ness of Latin1-only strings
#    'use charnames ":short"; $x="\N{latin:a with acute}"'
# op/recurse 12 - missing parens on recursive call makes it look like method
#    'sub f { f($x) }'
# op/subst 90 - inconsistent handling of utf8 under "use utf8"
# op/taint 29 - "use re 'taint'" deparsed in the wrong place wrt. block open
# op/tiehandle compile - "use strict" deparsed in the wrong place
# uni/tr_ several
# ext/B/t/xref 11 - line numbers when we add newlines to one-line subs
# ext/Data/Dumper/t/dumper compile
# ext/DB_file/several
# ext/Encode/several
# ext/Ernno/Errno warnings
# ext/IO/lib/IO/t/io_sel 23
# ext/PerlIO/t/encoding compile
# ext/POSIX/t/posix 6
# ext/Socket/Socket 8
# ext/Storable/t/croak compile
# lib/Attribute/Handlers/t/multi compile
# lib/bignum/ several
# lib/charnames 35
# lib/constant 32
# lib/English 40
# lib/ExtUtils/t/bytes 4
# lib/File/DosGlob compile
# lib/Filter/Simple/t/data 1
# lib/Math/BigInt/t/constant 1
# lib/Net/t/config Deparse-warning
# lib/overload compile
# lib/Switch/ several
# lib/Symbol 4
# lib/Test/Simple several
# lib/Term/Complete
# lib/Tie/File/t/29_downcopy 5
# lib/vars 22

# Object fields:
#
# in_coderef2text:
# True when deparsing via $deparse->coderef2text; false when deparsing the
# main program.
#
# 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
#
# curcvlex:
# Cached hash of lexical variables for curcv: keys are
# names prefixed with "m" or "o" (representing my/our), and
# each value is an array with two elements indicating the cop_seq
# of scopes in which a var of that name is valid and a third ele-
# ment referencing the pad name.
#
# curcop:
# COP for statement being deparsed
#
# curstash:
# name of the current package for deparsed code
#
# subs_todo:
# array of [cop_seq, CV, is_format?, name] for subs and formats we still
# want to deparse.  The fourth element is a pad name thingy for lexical
# subs or a string for special blocks.  For other subs, it is undef.  For
# lexical subs, CV may be undef, indicating a stub declaration.
#
# 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)
#
# subs_declared
# keys are names of subs for which we've printed declarations.
# That means we can omit parentheses from the arguments. It also means we
# need to put CORE:: on core functions of the same name.
#
# in_subst_repl
# True when deparsing the replacement part of a substitution.
#
# in_refgen
# True when deparsing the argument to \.
#
# 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.5           statements, but still print scopes as do { ... }
#  0             statement level
# -1             format body

# 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

# Semicolon handling:
#  - Individual statements are not deparsed with trailing semicolons.
#    (If necessary, \cK is tacked on to the end.)
#  - Whatever code joins statements together or emits them (lineseq,
#    scopeop, deparse_root) is responsible for adding semicolons where
#    necessary.
#  - use statements are deparsed with trailing semicolons because they are
#    immediately concatenated with the following statement.
#  - indent() removes semicolons wherever it sees \cK.


BEGIN { for (qw[ const stringify rv2sv list glob pushmark null aelem
		 nextstate dbstate rv2av rv2hv helem custom ]) {
    eval "sub OP_\U$_ () { " . opnumber($_) . "}"
}}

# _pessimise_walk(): recursively walk the optree of a sub,
# possibly undoing optimisations along the way.

sub _pessimise_walk {
    my ($self, $startop) = @_;

    return unless $$startop;
    my ($op, $prevop);
    for ($op = $startop; $$op; $prevop = $op, $op = $op->sibling) {
	my $ppname = $op->name;

	# pessimisations start here

	if ($ppname eq "padrange") {
	    # remove PADRANGE:
	    # the original optimisation either (1) changed this:
	    #    pushmark -> (various pad and list and null ops) -> the_rest
	    # or (2), for the = @_ case, changed this:
	    #    pushmark -> gv[_] -> rv2av -> (pad stuff)       -> the_rest
	    # into this:
	    #    padrange ----------------------------------------> the_rest
	    # so we just need to convert the padrange back into a
	    # pushmark, and in case (1), set its op_next to op_sibling,
	    # which is the head of the original chain of optimised-away
	    # pad ops, or for (2), set it to sibling->first, which is
	    # the original gv[_].

	    $B::overlay->{$$op} = {
		    type => OP_PUSHMARK,
		    name => 'pushmark',
		    private => ($op->private & OPpLVAL_INTRO),
	    };
	}

	# pessimisations end here

	if (class($op) eq 'PMOP'
	    && ref($op->pmreplroot)
	    && ${$op->pmreplroot}
	    && $op->pmreplroot->isa( 'B::OP' ))
	{
	    $self-> _pessimise_walk($op->pmreplroot);
	}

	if ($op->flags & OPf_KIDS) {
	    $self-> _pessimise_walk($op->first);
	}

    }
}


# _pessimise_walk_exe(): recursively walk the op_next chain of a sub,
# possibly undoing optimisations along the way.

sub _pessimise_walk_exe {
    my ($self, $startop, $visited) = @_;

    return unless $$startop;
    return if $visited->{$$startop};
    my ($op, $prevop);
    for ($op = $startop; $$op; $prevop = $op, $op = $op->next) {
	last if $visited->{$$op};
	$visited->{$$op} = 1;
	my $ppname = $op->name;
	if ($ppname =~
	    /^((and|d?or)(assign)?|(map|grep)while|range|cond_expr|once)$/
	    # entertry is also a logop, but its op_other invariably points
	    # into the same chain as the main execution path, so we skip it
	) {
	    $self->_pessimise_walk_exe($op->other, $visited);
	}
	elsif ($ppname eq "subst") {
	    $self->_pessimise_walk_exe($op->pmreplstart, $visited);
	}
	elsif ($ppname =~ /^(enter(loop|iter))$/) {
	    # redoop and nextop will already be covered by the main block
	    # of the loop
	    $self->_pessimise_walk_exe($op->lastop, $visited);
	}

	# pessimisations start here
    }
}

# Go through an optree and "remove" some optimisations by using an
# overlay to selectively modify or un-null some ops. Deparsing in the
# absence of those optimisations is then easier.
#
# Note that older optimisations are not removed, as Deparse was already
# written to recognise them before the pessimise/overlay system was added.

sub pessimise {
    my ($self, $root, $start) = @_;

    no warnings 'recursion';
    # walk tree in root-to-branch order
    $self->_pessimise_walk($root);

    my %visited;
    # walk tree in execution order
    $self->_pessimise_walk_exe($start, \%visited);
}


sub null {
    my $op = shift;
    return class($op) eq "NULL";
}


# Add a CV to the list of subs that still need deparsing.

sub todo {
    my $self = shift;
    my($cv, $is_form, $name) = @_;
    my $cvfile = $cv->FILE//'';
    return unless ($cvfile eq $0 || exists $self->{files}{$cvfile});
    my $seq;
    if ($cv->OUTSIDE_SEQ) {
	$seq = $cv->OUTSIDE_SEQ;
    } elsif (!null($cv->START) and is_state($cv->START)) {
	$seq = $cv->START->cop_seq;
    } else {
	$seq = 0;
    }
    push @{$self->{'subs_todo'}}, [$seq, $cv, $is_form, $name];
}


# Pop the next sub from the todo list and deparse it

sub next_todo {
    my $self = shift;
    my $ent = shift @{$self->{'subs_todo'}};
    my ($seq, $cv, $is_form, $name) = @$ent;

    # any 'use strict; package foo' that should come before the sub
    # declaration to sync with the first COP of the sub
    my $pragmata = '';
    if ($cv and !null($cv->START) and is_state($cv->START))  {
        $pragmata = $self->pragmata($cv->START);
    }

    if (ref $name) { # lexical sub
	# emit the sub.
	my @text;
	my $flags = $name->FLAGS;
	push @text,
	    !$cv || $seq <= $name->COP_SEQ_RANGE_LOW
		? $self->keyword($flags & SVpad_OUR
				    ? "our"
				    : $flags & SVpad_STATE
					? "state"
					: "my") . " "
		: "";
	# XXX We would do $self->keyword("sub"), but ‘my CORE::sub’
	#     doesn’t work and ‘my sub’ ignores a &sub in scope.  I.e.,
	#     we have a core bug here.
	push @text, "sub " . substr $name->PVX, 1;
	if ($cv) {
	    # my sub foo { }
	    push @text,  " " . $self->deparse_sub($cv);
	    $text[-1] =~ s/ ;$/;/;
	}
	else {
	    # my sub foo;
	    push @text, ";\n";
	}
	return $pragmata . join "", @text;
    }

    my $gv = $cv->GV;
    $name //= $self->gv_name($gv);
    if ($is_form) {
	return $pragmata . $self->keyword("format") . " $name =\n"
	    . $self->deparse_format($cv). "\n";
    } else {
	my $use_dec;
	if ($name eq "BEGIN") {
	    $use_dec = $self->begin_is_use($cv);
	    if (defined ($use_dec) and $self->{'expand'} < 5) {
		return $pragmata if 0 == length($use_dec);

                #  XXX bit of a hack: Test::More's use_ok() method
                #  builds a fake use statement which deparses as, e.g.
                #      use Net::Ping (@{$args[0];});
                #  As well as being superfluous (the use_ok() is deparsed
                #  too) and ugly, it fails under use strict and otherwise
                #  makes use of a lexical var that's not in scope.
                #  So strip it out.
                return $pragmata
                            if $use_dec =~ /^use \S+ \(@\{\$args\[0\];\}\);/;

		$use_dec =~ s/^(use|no)\b/$self->keyword($1)/e;
	    }
	}
	my $l = '';
	if ($self->{'linenums'}) {
	    my $line = $gv->LINE;
	    my $file = $gv->FILE;
	    $l = "\n\f#line $line \"$file\"\n";
	}
	my $p = '';
	my $stash;
	if (class($cv->STASH) ne "SPECIAL") {
	    $stash = $cv->STASH->NAME;
	    if ($stash ne $self->{'curstash'}) {
		$p = $self->keyword("package") . " $stash;\n";
		$name = "$self->{'curstash'}::$name" unless $name =~ /::/;
		$self->{'curstash'} = $stash;
	    }
	}
	if ($use_dec) {
	    return "$pragmata$p$l$use_dec";
	}
        if ( $name !~ /::/ and $self->lex_in_scope("&$name")
                            || $self->lex_in_scope("&$name", 1) )
        {
            $name = "$self->{'curstash'}::$name";
        } elsif (defined $stash) {
            $name =~ s/^\Q$stash\E::(?!\z|.*::)//;
        }
	my $ret = "$pragmata${p}${l}" . $self->keyword("sub") . " $name "
	      . $self->deparse_sub($cv);
	$self->{'subs_declared'}{$name} = 1;
	return $ret;
    }
}


# Return a "use" declaration for this BEGIN block, if appropriate
sub begin_is_use {
    my ($self, $cv) = @_;
    my $root = $cv->ROOT;
    local @$self{qw'curcv curcvlex'} = ($cv);
    local $B::overlay = {};
    $self->pessimise($root, $cv->START);
#require B::Debug;
#B::walkoptree($cv->ROOT, "debug");
    my $lineseq = $root->first;
    return if $lineseq->name ne "lineseq";

    my $req_op = $lineseq->first->sibling;
    return if $req_op->name ne "require";

    my $module;
    if ($req_op->first->private & OPpCONST_BARE) {
	# Actually it should always be a bareword
	$module = $self->const_sv($req_op->first)->PV;
	$module =~ s[/][::]g;
	$module =~ s/.pm$//;
    }
    else {
	$module = $self->const($self->const_sv($req_op->first), 6);
    }

    my $version;
    my $version_op = $req_op->sibling;
    return if class($version_op) eq "NULL";
    if ($version_op->name eq "lineseq") {
	# We have a version parameter; skip nextstate & pushmark
	my $constop = $version_op->first->next->next;

	return unless $self->const_sv($constop)->PV eq $module;
	$constop = $constop->sibling;
	$version = $self->const_sv($constop);
	if (class($version) eq "IV") {
	    $version = $version->int_value;
	} elsif (class($version) eq "NV") {
	    $version = $version->NV;
	} elsif (class($version) ne "PVMG") {
	    # Includes PVIV and PVNV
	    $version = $version->PV;
	} else {
	    # version specified as a v-string
	    $version = 'v'.join '.', map ord, split //, $version->PV;
	}
	$constop = $constop->sibling;
	return if $constop->name ne "method_named";
	return if $self->meth_sv($constop)->PV ne "VERSION";
    }

    $lineseq = $version_op->sibling;
    return if $lineseq->name ne "lineseq";
    my $entersub = $lineseq->first->sibling;
    if ($entersub->name eq "stub") {
	return "use $module $version ();\n" if defined $version;
	return "use $module ();\n";
    }
    return if $entersub->name ne "entersub";

    # See if there are import arguments
    my $args = '';

    my $svop = $entersub->first->sibling; # Skip over pushmark
    return unless $self->const_sv($svop)->PV eq $module;

    # Pull out the arguments
    for ($svop=$svop->sibling; index($svop->name, "method_") != 0;
		$svop = $svop->sibling) {
	$args .= ", " if length($args);
	$args .= $self->deparse($svop, 6);
    }

    my $use = 'use';
    my $method_named = $svop;
    return if $method_named->name ne "method_named";
    my $method_name = $self->meth_sv($method_named)->PV;

    if ($method_name eq "unimport") {
	$use = 'no';
    }

    # Certain pragmas are dealt with using hint bits,
    # so we ignore them here
    if ($module eq 'strict' || $module eq 'integer'
	|| $module eq 'bytes' || $module eq 'warnings'
	|| $module eq 'feature') {
	return "";
    }

    if (defined $version && length $args) {
	return "$use $module $version ($args);\n";
    } elsif (defined $version) {
	return "$use $module $version;\n";
    } elsif (length $args) {
	return "$use $module ($args);\n";
    } else {
	return "$use $module;\n";
    }
}

sub stash_subs {
    my ($self, $pack, $seen) = @_;
    my (@ret, $stash);
    if (!defined $pack) {
	$pack = '';
	$stash = \%::;
    }
    else {
	$pack =~ s/(::)?$/::/;
	no strict 'refs';
	$stash = \%{"main::$pack"};
    }
    return
	if ($seen ||= {})->{
	    $INC{"overload.pm"} ? overload::StrVal($stash) : $stash
	   }++;
    my %stash = svref_2object($stash)->ARRAY;
    while (my ($key, $val) = each %stash) {
	my $flags = $val->FLAGS;
	if ($flags & SVf_ROK) {
	    # A reference.  Dump this if it is a reference to a CV.  If it
	    # is a constant acting as a proxy for a full subroutine, then
	    # we may or may not have to dump it.  If some form of perl-
	    # space visible code must have created it, be it a use
	    # statement, or some direct symbol-table manipulation code that
	    # we will deparse, then we don’t want to dump it.  If it is the
	    # result of a declaration like sub f () { 42 } then we *do*
	    # want to dump it.  The only way to distinguish these seems
	    # to be the SVs_PADTMP flag on the constant, which is admit-
	    # tedly a hack.
	    my $class = class(my $referent = $val->RV);
	    if ($class eq "CV") {
		$self->todo($referent, 0);
	    } elsif (
		$class !~ /^(AV|HV|CV|FM|IO|SPECIAL)\z/
		# A more robust way to write that would be this, but B does
		# not provide the SVt_ constants:
		# ($referent->FLAGS & B::SVTYPEMASK) < B::SVt_PVAV
		and $referent->FLAGS & SVs_PADTMP
	    ) {
		push @{$self->{'protos_todo'}}, [$pack . $key, $val];
	    }
	} elsif ($flags & (SVf_POK|SVf_IOK)) {
	    # Just a prototype. As an ugly but fairly effective way
	    # to find out if it belongs here is to see if the AUTOLOAD
	    # (if any) for the stash was defined in one of our files.
	    my $A = $stash{"AUTOLOAD"};
	    if (defined ($A) && class($A) eq "GV" && defined($A->CV)
		&& class($A->CV) eq "CV") {
		my $AF = $A->FILE;
		next unless $AF eq $0 || exists $self->{'files'}{$AF};
	    }
	    push @{$self->{'protos_todo'}},
		 [$pack . $key, $flags & SVf_POK ? $val->PV: undef];
	} elsif (class($val) eq "GV") {
	    if (class(my $cv = $val->CV) ne "SPECIAL") {
		next if $self->{'subs_done'}{$$val}++;
		next if $$val != ${$cv->GV};   # Ignore imposters
		$self->todo($cv, 0);
	    }
	    if (class(my $cv = $val->FORM) ne "SPECIAL") {
		next if $self->{'forms_done'}{$$val}++;
		next if $$val != ${$cv->GV};   # Ignore imposters
		$self->todo($cv, 1);
	    }
	    if (class($val->HV) ne "SPECIAL" && $key =~ /::$/) {
		$self->stash_subs($pack . $key, $seen);
	    }
	}
    }
}

sub print_protos {
    my $self = shift;
    my $ar;
    my @ret;
    foreach $ar (@{$self->{'protos_todo'}}) {
	my $body = defined $ar->[1]
		? ref $ar->[1]
		    ? " () {\n    " . $self->const($ar->[1]->RV,0) . ";\n}"
		    : " (". $ar->[1] . ");"
		: ";";
	push @ret, "sub " . $ar->[0] .  "$body\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->{'cuddle'} = "\n";
    $self->{'curcop'} = undef;
    $self->{'curstash'} = "main";
    $self->{'ex_const'} = "'???'";
    $self->{'expand'} = 0;
    $self->{'files'} = {};
    $self->{'indent_size'} = 4;
    $self->{'linenums'} = 0;
    $self->{'parens'} = 0;
    $self->{'subs_todo'} = [];
    $self->{'unquote'} = 0;
    $self->{'use_dumper'} = 0;
    $self->{'use_tabs'} = 0;

    $self->{'ambient_arybase'} = 0;
    $self->{'ambient_warnings'} = undef; # Assume no lexical warnings
    $self->{'ambient_hints'} = 0;
    $self->{'ambient_hinthash'} = undef;
    $self->init();

    while (my $arg = shift @_) {
	if ($arg eq "-d") {
	    $self->{'use_dumper'} = 1;
	    require Data::Dumper;
	} elsif ($arg =~ /^-f(.*)/) {
	    $self->{'files'}{$1} = 1;
	} elsif ($arg eq "-l") {
	    $self->{'linenums'} = 1;
	} elsif ($arg eq "-p") {
	    $self->{'parens'} = 1;
	} elsif ($arg eq "-P") {
	    $self->{'noproto'} = 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;
}

{
    # Mask out the bits that L<warnings::register> uses
    my $WARN_MASK;
    BEGIN {
	$WARN_MASK = $warnings::Bits{all} | $warnings::DeadBits{all};
    }
    sub WARN_MASK () {
	return $WARN_MASK;
    }
}

# Initialise the contextual information, either from
# defaults provided with the ambient_pragmas method,
# or from perl's own defaults otherwise.
sub init {
    my $self = shift;

    $self->{'arybase'}  = $self->{'ambient_arybase'};
    $self->{'warnings'} = defined ($self->{'ambient_warnings'})
				? $self->{'ambient_warnings'} & WARN_MASK
				: undef;
    $self->{'hints'}    = $self->{'ambient_hints'};
    $self->{'hints'} &= 0xFF if $] < 5.009;
    $self->{'hinthash'} = $self->{'ambient_hinthash'};

    # also a convenient place to clear out subs_declared
    delete $self->{'subs_declared'};
}

sub compile {
    my(@args) = @_;
    return sub {
	my $self = B::Deparse->new(@args);
	# First deparse command-line args
	if (defined $^I) { # deparse -i
	    print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
	}
	if ($^W) { # deparse -w
	    print qq(BEGIN { \$^W = $^W; }\n);
	}
	if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
	    my $fs = perlstring($/) || 'undef';
	    my $bs = perlstring($O::savebackslash) || 'undef';
	    print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
	}
	my @BEGINs  = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
	my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
	    ? B::unitcheck_av->ARRAY
	    : ();
	my @CHECKs  = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
	my @INITs   = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
	my @ENDs    = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
	my @names = qw(BEGIN UNITCHECK CHECK INIT END);
	my @blocks = \(@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs);
	while (@names) {
	    my ($name, $blocks) = (shift @names, shift @blocks);
	    for my $block (@$blocks) {
		$self->todo($block, 0, $name);
	    }
	}
	$self->stash_subs();
	local($SIG{"__DIE__"}) =
	  sub {
	      if ($self->{'curcop'}) {
		  my $cop = $self->{'curcop'};
		  my($line, $file) = ($cop->line, $cop->file);
		  print STDERR "While deparsing $file near line $line,\n";
	      }
	    };
	$self->{'curcv'} = main_cv;
	$self->{'curcvlex'} = undef;
	print $self->print_protos;
	@{$self->{'subs_todo'}} =
	  sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
	my $root = main_root;
	local $B::overlay = {};
	unless (null $root) {
	    $self->pad_subs($self->{'curcv'});
	    # Check for a stub-followed-by-ex-cop, resulting from a program
	    # consisting solely of sub declarations.  For backward-compati-
	    # bility (and sane output) we don’t want to emit the stub.
	    #   leave
	    #     enter
	    #     stub
	    #     ex-nextstate (or ex-dbstate)
	    my $kid;
	    if ( $root->name eq 'leave'
	     and ($kid = $root->first)->name eq 'enter'
	     and !null($kid = $kid->sibling) and $kid->name eq 'stub'
	     and !null($kid = $kid->sibling) and $kid->name eq 'null'
	     and class($kid) eq 'COP' and null $kid->sibling )
	    {
		# ignore
	    } else {
		$self->pessimise($root, main_start);
		print $self->indent($self->deparse_root($root)), "\n";
	    }
	}
	my @text;
	while (scalar(@{$self->{'subs_todo'}})) {
	    push @text, $self->next_todo;
	}
	print $self->indent(join("", @text)), "\n" if @text;

	# Print __DATA__ section, if necessary
	no strict 'refs';
	my $laststash = defined $self->{'curcop'}
	    ? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
	if (defined *{$laststash."::DATA"}{IO}) {
	    print $self->keyword("package") . " $laststash;\n"
		unless $laststash eq $self->{'curstash'};
	    print $self->keyword("__DATA__") . "\n";
	    print readline(*{$laststash."::DATA"});
	}
    }
}

sub coderef2text {
    my $self = shift;
    my $sub = shift;
    croak "Usage: ->coderef2text(CODEREF)" unless UNIVERSAL::isa($sub, "CODE");

    $self->init();
    local $self->{in_coderef2text} = 1;
    return $self->indent($self->deparse_sub(svref_2object($sub)));
}

my %strict_bits = do {
    local $^H;
    map +($_ => strict::bits($_)), qw/refs subs vars/
};

sub ambient_pragmas {
    my $self = shift;
    my ($arybase, $hint_bits, $warning_bits, $hinthash) = (0, 0);

    while (@_ > 1) {
	my $name = shift();
	my $val  = shift();

	if ($name eq 'strict') {
	    require strict;

	    if ($val eq 'none') {
		$hint_bits &= $strict_bits{$_} for qw/refs subs vars/;
		next();
	    }

	    my @names;
	    if ($val eq "all") {
		@names = qw/refs subs vars/;
	    }
	    elsif (ref $val) {
		@names = @$val;
	    }
	    else {
		@names = split' ', $val;
	    }
	    $hint_bits |= $strict_bits{$_} for @names;
	}

	elsif ($name eq '$[') {
	    if (OPpCONST_ARYBASE) {
		$arybase = $val;
	    } else {
		croak "\$[ can't be non-zero on this perl" unless $val == 0;
	    }
	}

	elsif ($name eq 'integer'
	    || $name eq 'bytes'
	    || $name eq 'utf8') {
	    require "$name.pm";
	    if ($val) {
		$hint_bits |= ${$::{"${name}::"}{"hint_bits"}};
	    }
	    else {
		$hint_bits &= ~${$::{"${name}::"}{"hint_bits"}};
	    }
	}

	elsif ($name eq 're') {
	    require re;
	    if ($val eq 'none') {
		$hint_bits &= ~re::bits(qw/taint eval/);
		next();
	    }

	    my @names;
	    if ($val eq 'all') {
		@names = qw/taint eval/;
	    }
	    elsif (ref $val) {
		@names = @$val;
	    }
	    else {
		@names = split' ',$val;
	    }
	    $hint_bits |= re::bits(@names);
	}

	elsif ($name eq 'warnings') {
	    if ($val eq 'none') {
		$warning_bits = $warnings::NONE;
		next();
	    }

	    my @names;
	    if (ref $val) {
		@names = @$val;
	    }
	    else {
		@names = split/\s+/, $val;
	    }

	    $warning_bits = $warnings::NONE if !defined ($warning_bits);
	    $warning_bits |= warnings::bits(@names);
	}

	elsif ($name eq 'warning_bits') {
	    $warning_bits = $val;
	}

	elsif ($name eq 'hint_bits') {
	    $hint_bits = $val;
	}

	elsif ($name eq '%^H') {
	    $hinthash = $val;
	}

	else {
	    croak "Unknown pragma type: $name";
	}
    }
    if (@_) {
	croak "The ambient_pragmas method expects an even number of args";
    }

    $self->{'ambient_arybase'} = $arybase;
    $self->{'ambient_warnings'} = $warning_bits;
    $self->{'ambient_hints'} = $hint_bits;
    $self->{'ambient_hinthash'} = $hinthash;
}

# This method is the inner loop, so try to keep it simple
sub deparse {
    my $self = shift;
    my($op, $cx) = @_;

    Carp::confess("Null op in deparse") if !defined($op)
					|| class($op) eq "NULL";
    my $meth = "pp_" . $op->name;
    return $self->$meth($op, $cx);
}

sub indent {
    my $self = shift;
    my $txt = shift;
    # \cK also swallows a preceding line break when followed by a
    # semicolon.
    $txt =~ s/\n\cK;//g;
    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 (index($line, "\f") > 0) {
		$line =~ s/\f/\n/;
	}
	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 pad_subs {
    my ($self, $cv) = @_;
    my $padlist = $cv->PADLIST;
    my @names = $padlist->ARRAYelt(0)->ARRAY;
    my @values = $padlist->ARRAYelt(1)->ARRAY;
    my @todo;
  PADENTRY:
    for my $ix (0.. $#names) { for $_ ($names[$ix]) {
	next if class($_) eq "SPECIAL";
	my $name = $_->PVX;
	if (defined $name && $name =~ /^&./) {
	    my $low = $_->COP_SEQ_RANGE_LOW;
	    my $flags = $_->FLAGS;
	    my $outer = $flags & PADNAMEt_OUTER;
	    if ($flags & SVpad_OUR) {
		push @todo, [$low, undef, 0, $_]
		          # [seq, no cv, not format, padname]
		    unless $outer;
		next;
	    }
	    my $protocv = $flags & SVpad_STATE
		? $values[$ix]
		: $_->PROTOCV;
	    if (class ($protocv) ne 'CV') {
		my $flags = $flags;
		my $cv = $cv;
		my $name = $_;
		while ($flags & PADNAMEt_OUTER && class ($protocv) ne 'CV')
		{
		    $cv = $cv->OUTSIDE;
		    next PADENTRY if class($cv) eq 'SPECIAL'; # XXX freed?
		    my $padlist = $cv->PADLIST;
		    my $ix = $name->PARENT_PAD_INDEX;
		    $name = $padlist->NAMES->ARRAYelt($ix);
		    $flags = $name->FLAGS;
		    $protocv = $flags & SVpad_STATE
			? $padlist->ARRAYelt(1)->ARRAYelt($ix)
			: $name->PROTOCV;
		}
	    }
	    my $defined_in_this_sub = ${$protocv->OUTSIDE} == $$cv || do {
		my $other = $protocv->PADLIST;
		$$other && $other->outid == $padlist->id;
	    };
	    if ($flags & PADNAMEt_OUTER) {
		next unless $defined_in_this_sub;
		push @todo, [$protocv->OUTSIDE_SEQ, $protocv, 0, $_];
		next;
	    }
	    my $outseq = $protocv->OUTSIDE_SEQ;
	    if ($outseq <= $low) {
		# defined before its name is visible, so it’s gotta be
		# declared and defined at once: my sub foo { ... }
		push @todo, [$low, $protocv, 0, $_];
	    }
	    else {
		# declared and defined separately: my sub f; sub f { ... }
		push @todo, [$low, undef, 0, $_];
		push @todo, [$outseq, $protocv, 0, $_]
		    if $defined_in_this_sub;
	    }
	}
    }}
    @{$self->{'subs_todo'}} =
	sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}}, @todo
}


# deparse_argops(): deparse, if possible, a sequence of argcheck + argelem
# ops into a subroutine signature. If successful, return the first op
# following the signature ops plus the signature string; else return the
# empty list.
#
# Normally a bunch of argelem ops will have been generated by the
# signature parsing, but it's possible that ops have been added manually
# or altered. In this case we "return ()" and fall back to general
# deparsing of the individual sigelems as 'my $x = $_[N]' etc.
#
# We're only called if the first two ops are nextstate and argcheck.

sub deparse_argops {
    my ($self, $firstop, $cv) = @_;

    my @sig;
    my $o = $firstop;
    return if $o->label; #first nextstate;

    # OP_ARGCHECK

    $o = $o->sibling;
    my ($params, $opt_params, $slurpy) = $o->aux_list($cv);
    my $mandatory = $params - $opt_params;
    my $seen_slurpy = 0;
    my $last_ix = -1;

    # keep looking for valid nextstate + argelem pairs

    while (1) {
        # OP_NEXTSTATE
        $o = $o->sibling;
        last unless $$o;
        last unless $o->name =~ /^(next|db)state$/;
        last if $o->label;

        # OP_ARGELEM
        my $o2 = $o->sibling;
        last unless $$o2;

        if ($o2->name eq 'argelem') {
            my $ix  = $o2->string($cv);
            while (++$last_ix < $ix) {
                push @sig, $last_ix <  $mandatory ? '$' : '$=';
            }
            my $var = $self->padname($o2->targ);
            if ($var =~ /^[@%]/) {
                return if $seen_slurpy;
                $seen_slurpy = 1;
                return if $ix != $params or !$slurpy
                            or substr($var,0,1) ne $slurpy;
            }
            else {
                return if $ix >= $params;
            }
            if ($o2->flags & OPf_KIDS) {
                my $kid = $o2->first;
                return unless $$kid and $kid->name eq 'argdefelem';
                my $def = $self->deparse($kid->first, 7);
                $def = "($def)" if $kid->first->flags & OPf_PARENS;
                $var .= " = $def";
            }
            push @sig, $var;
        }
        elsif ($o2->name eq 'null'
               and ($o2->flags & OPf_KIDS)
               and $o2->first->name eq 'argdefelem')
        {
            # special case - a void context default expression: $ = expr

            my $defop = $o2->first;
            my $ix = $defop->targ;
            while (++$last_ix < $ix) {
                push @sig, $last_ix <  $mandatory ? '$' : '$=';
            }
            return if $last_ix >= $params
                    or $last_ix < $mandatory;
            my $def = $self->deparse($defop->first, 7);
            $def = "($def)" if $defop->first->flags & OPf_PARENS;
            push @sig, '$ = ' . $def;
        }
        else {
            last;
        }

        $o = $o2;
    }

    while (++$last_ix < $params) {
        push @sig, $last_ix <  $mandatory ? '$' : '$=';
    }
    push @sig, $slurpy if $slurpy and !$seen_slurpy;

    return ($o, join(', ', @sig));
}

# Deparse a sub. Returns everything except the 'sub foo',
# e.g.  ($$) : method { ...; }
# or    ($a, $b) : prototype($$) lvalue;

sub deparse_sub {
    my $self = shift;
    my $cv = shift;
    my @attrs;
    my $protosig; # prototype or signature (what goes in the (....))

Carp::confess("NULL in deparse_sub") if !defined($cv) || $cv->isa("B::NULL");
Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
    local $self->{'curcop'} = $self->{'curcop'};

    my $has_sig = $self->{hinthash}{feature_signatures};
    if ($cv->FLAGS & SVf_POK) {
	my $proto = $cv->PV;
	if ($has_sig) {
            push @attrs, "prototype($proto)";
        }
        else {
            $protosig = $proto;
        }
    }
    if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE|CVf_ANONCONST)) {
        push @attrs, "lvalue" if $cv->CvFLAGS & CVf_LVALUE;
        push @attrs, "locked" if $cv->CvFLAGS & CVf_LOCKED;
        push @attrs, "method" if $cv->CvFLAGS & CVf_METHOD;
        push @attrs, "const"  if $cv->CvFLAGS & CVf_ANONCONST;
    }

    local($self->{'curcv'}) = $cv;
    local($self->{'curcvlex'});
    local(@$self{qw'curstash warnings hints hinthash'})
		= @$self{qw'curstash warnings hints hinthash'};
    my $body;
    my $root = $cv->ROOT;
    local $B::overlay = {};
    if (not null $root) {
	$self->pad_subs($cv);
	$self->pessimise($root, $cv->START);
	my $lineseq = $root->first;
	if ($lineseq->name eq "lineseq") {
	    my $firstop = $lineseq->first;

            if ($has_sig) {
                my $o2;
                # try to deparse first few ops as a signature if possible
                if (     $$firstop
                     and $firstop->name =~  /^(next|db)state$/
                     and (($o2 = $firstop->sibling))
                     and $$o2)
                {
                    if ($o2->name eq 'argcheck') {
                        my ($nexto, $sig) = $self->deparse_argops($firstop, $cv);
                        if (defined $nexto) {
                            $firstop = $nexto;
                            $protosig = $sig;
                        }
                    }
                }
            }

            my @ops;
	    for (my $o = $firstop; $$o; $o=$o->sibling) {
		push @ops, $o;
	    }
	    $body = $self->lineseq(undef, 0, @ops).";";
            if (!$has_sig and $ops[-1]->name =~ /^(next|db)state$/) {
                # this handles void context in
                #   use feature signatures; sub ($=1) {}
                $body .= "\n()";
            }
	    my $scope_en = $self->find_scope_en($lineseq);
	    if (defined $scope_en) {
		my $subs = join"", $self->seq_subs($scope_en);
		$body .= ";\n$subs" if length($subs);
	    }
	}
	else {
	    $body = $self->deparse($root->first, 0);
	}
        $body = "{\n\t$body\n\b}";
    }
    else {
	my $sv = $cv->const_sv;
	if ($$sv) {
	    # uh-oh. inlinable sub... format it differently
	    $body = "{ " . $self->const($sv, 0) . " }\n";
	} else { # XSUB? (or just a declaration)
	    $body = ';'
	}
    }
    $protosig = defined $protosig ? "($protosig) " : "";
    my $attrs = '';
    $attrs = ': ' . join('', map "$_ ", @attrs) if @attrs;
    return "$protosig$attrs$body\n";
}

sub deparse_format {
    my $self = shift;
    my $form = shift;
    my @text;
    local($self->{'curcv'}) = $form;
    local($self->{'curcvlex'});
    local($self->{'in_format'}) = 1;
    local(@$self{qw'curstash warnings hints hinthash'})
		= @$self{qw'curstash warnings hints hinthash'};
    my $op = $form->ROOT;
    local $B::overlay = {};
    $self->pessimise($op, $form->START);
    my $kid;
    return "\f." if $op->first->name eq 'stub'
                || $op->first->name eq 'nextstate';
    $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, "\f".$self->const_sv($kid)->PV;
	$kid = $kid->sibling;
	for (; not null $kid; $kid = $kid->sibling) {
	    push @exprs, $self->deparse($kid, -1);
	    $exprs[-1] =~ s/;\z//;
	}
	push @text, "\f".join(", ", @exprs)."\n" if @exprs;
	$op = $op->sibling;
    }
    return join("", @text) . "\f.";
}

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")
		 ));
}

# Check if the op and its sibling are the initialization and the rest of a
# for (..;..;..) { ... } loop
sub is_for_loop {
    my $op = shift;
    # This OP might be almost anything, though it won't be a
    # nextstate. (It's the initialization, so in the canonical case it
    # will be an sassign.) The sibling is (old style) a lineseq whose
    # first child is a nextstate and whose second is a leaveloop, or
    # (new style) an unstack whose sibling is a leaveloop.
    my $lseq = $op->sibling;
    return 0 unless !is_state($op) and !null($lseq);
    if ($lseq->name eq "lineseq") {
	if ($lseq->first && !null($lseq->first) && is_state($lseq->first)
	    && (my $sib = $lseq->first->sibling)) {
	    return (!null($sib) && $sib->name eq "leaveloop");
	}
    } elsif ($lseq->name eq "unstack" && ($lseq->flags & OPf_SPECIAL)) {
	my $sib = $lseq->sibling;
	return $sib && !null($sib) && $sib->name eq "leaveloop";
    }
    return 0;
}

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'}) {
	$kid =  $self->deparse($kid, 1);
 	if ($name eq "umask" && $kid =~ /^\d+$/) {
	    $kid = sprintf("%#o", $kid);
	}
	return $self->keyword($name) . "($kid)";
    } else {
	$kid = $self->deparse($kid, 16);
 	if ($name eq "umask" && $kid =~ /^\d+$/) {
	    $kid = sprintf("%#o", $kid);
	}
	$name = $self->keyword($name);
	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 find_our_type {
    my ($self, $name) = @_;
    $self->populate_curcvlex() if !defined $self->{'curcvlex'};
    my $seq = $self->{'curcop'} ? $self->{'curcop'}->cop_seq : 0;
    for my $a (@{$self->{'curcvlex'}{"o$name"}}) {
	my ($st, undef, $padname) = @$a;
	if ($st >= $seq && $padname->FLAGS & SVpad_TYPED) {
	    return $padname->SvSTASH->NAME;
	}
    }
    return '';
}

sub maybe_local {
    my $self = shift;
    my($op, $cx, $text) = @_;
    my $name = $op->name;
    my $our_intro = ($name =~ /^(?:(?:gv|rv2)[ash]v|split|refassign
				  |lv(?:av)?ref)$/x)
			? OPpOUR_INTRO
			: 0;
    my $lval_intro = $name eq 'split' ? 0 : OPpLVAL_INTRO;
    # The @a in \(@a) isn't in ref context, but only when the
    # parens are there.
    my $need_parens = $self->{'in_refgen'} && $name =~ /[ah]v\z/
		   && ($op->flags & (OPf_PARENS|OPf_REF)) == OPf_PARENS;
    if ((my $priv = $op->private) & ($lval_intro|$our_intro)) {
	my @our_local;
	push @our_local, "local" if $priv & $lval_intro;
	push @our_local, "our"   if $priv & $our_intro;
	my $our_local = join " ", map $self->keyword($_), @our_local;
	if( $our_local[-1] eq 'our' ) {
	    if ( $text !~ /^\W(\w+::)*\w+\z/
	     and !utf8::decode($text) || $text !~ /^\W(\w+::)*\w+\z/
	    ) {
		die "Unexpected our($text)\n";
	    }
	    $text =~ s/(\w+::)+//;

	    if (my $type = $self->find_our_type($text)) {
		$our_local .= ' ' . $type;
	    }
	}
	return $need_parens ? "($text)" : $text
	    if $self->{'avoid_local'}{$$op};
	if ($need_parens) {
	    return "$our_local($text)";
	} elsif (want_scalar($op)) {
	    return "$our_local $text";
	} else {
	    return $self->maybe_parens_func("$our_local", $text, $cx, 16);
	}
    } else {
	return $need_parens ? "($text)" : $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->ARRAYelt(0)->ARRAYelt($targ);
}

sub maybe_my {
    my $self = shift;
    my($op, $cx, $text, $padname, $forbid_parens) = @_;
    # The @a in \(@a) isn't in ref context, but only when the
    # parens are there.
    my $need_parens = !$forbid_parens && $self->{'in_refgen'}
		   && $op->name =~ /[ah]v\z/
		   && ($op->flags & (OPf_PARENS|OPf_REF)) == OPf_PARENS;
    # The @a in \my @a must not have parens.
    if (!$need_parens && $self->{'in_refgen'}) {
	$forbid_parens = 1;
    }
    if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
	# Check $padname->FLAGS for statehood, rather than $op->private,
	# because enteriter ops do not carry the flag.
	my $my =
	    $self->keyword($padname->FLAGS & SVpad_STATE ? "state" : "my");
	if ($padname->FLAGS & SVpad_TYPED) {
	    $my .= ' ' . $padname->SvSTASH->NAME;
	}
	if ($need_parens) {
	    return "$my($text)";
	} elsif ($forbid_parens || want_scalar($op)) {
	    return "$my $text";
	} else {
	    return $self->maybe_parens_func($my, $text, $cx, 16);
	}
    } else {
	return $need_parens ? "($text)" : $text;
    }
}

# The following OPs don't have functions:

# pp_padany -- does not exist after parsing

sub AUTOLOAD {
    if ($AUTOLOAD =~ s/^.*::pp_//) {
	warn "unexpected OP_".
	  ($_[1]->type == OP_CUSTOM ? "CUSTOM ($AUTOLOAD)" : uc $AUTOLOAD);
	return "XXX";
    } else {
	die "Undefined subroutine $AUTOLOAD called";
    }
}

sub DESTROY {}	#	Do not AUTOLOAD

# $root should be the op which represents the root of whatever
# we're sequencing here. If it's undefined, then we don't append
# any subroutine declarations to the deparsed ops, otherwise we
# append appropriate declarations.
sub lineseq {
    my($self, $root, $cx, @ops) = @_;
    my($expr, @exprs);

    my $out_cop = $self->{'curcop'};
    my $out_seq = defined($out_cop) ? $out_cop->cop_seq : undef;
    my $limit_seq;
    if (defined $root) {
	$limit_seq = $out_seq;
	my $nseq;
	$nseq = $self->find_scope_st($root->sibling) if ${$root->sibling};
	$limit_seq = $nseq if !defined($limit_seq)
			   or defined($nseq) && $nseq < $limit_seq;
    }
    $limit_seq = $self->{'limit_seq'}
	if defined($self->{'limit_seq'})
	&& (!defined($limit_seq) || $self->{'limit_seq'} < $limit_seq);
    local $self->{'limit_seq'} = $limit_seq;

    $self->walk_lineseq($root, \@ops,
		       sub { push @exprs, $_[0]} );

    my $sep = $cx ? '; ' : ";\n";
    my $body = join($sep, grep {length} @exprs);
    my $subs = "";
    if (defined $root && defined $limit_seq && !$self->{'in_format'}) {
	$subs = join "\n", $self->seq_subs($limit_seq);
    }
    return join($sep, grep {length} $body, $subs);
}

sub scopeop {
    my($real_block, $self, $op, $cx) = @_;
    my $kid;
    my @kids;

    local(@$self{qw'curstash warnings hints hinthash'})
		= @$self{qw'curstash warnings hints hinthash'} 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 = $self->keyword("while");
	    } elsif ($name eq "or") {
		$name = $self->keyword("until");
	    } else { # no conditional -> while 1 or until 0
		return $self->deparse($top->first, 1) . " "
		     . $self->keyword("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)
	my $body = $self->lineseq($op, 0, @kids);
	return is_lexical_subs(@kids)
		? $body
		: ($self->lex_in_scope("&do") ? "CORE::do" : "do")
		 . " {\n\t$body\n\b}";
    } else {
	my $lineseq = $self->lineseq($op, $cx, @kids);
	return (length ($lineseq) ? "$lineseq;" : "");
    }
}

sub pp_scope { scopeop(0, @_); }
sub pp_lineseq { scopeop(0, @_); }
sub pp_leave { scopeop(1, @_); }

# This is a special case of scopeop and lineseq, for the case of the
# main_root. The difference is that we print the output statements as
# soon as we get them, for the sake of impatient users.
sub deparse_root {
    my $self = shift;
    my($op) = @_;
    local(@$self{qw'curstash warnings hints hinthash'})
      = @$self{qw'curstash warnings hints hinthash'};
    my @kids;
    return if null $op->first; # Can happen, e.g., for Bytecode without -k
    for (my $kid = $op->first->sibling; !null($kid); $kid = $kid->sibling) {
	push @kids, $kid;
    }
    $self->walk_lineseq($op, \@kids,
			sub { return unless length $_[0];
			      print $self->indent($_[0].';');
			      print "\n"
				unless $_[1] == $#kids;
			  });
}

sub walk_lineseq {
    my ($self, $op, $kids, $callback) = @_;
    my @kids = @$kids;
    for (my $i = 0; $i < @kids; $i++) {
	my $expr = "";
	if (is_state $kids[$i]) {
	    $expr = $self->deparse($kids[$i++], 0);
	    if ($i > $#kids) {
		$callback->($expr, $i);
		last;
	    }
	}
	if (is_for_loop($kids[$i])) {
	    $callback->($expr . $self->for_loop($kids[$i], 0),
		$i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1);
	    next;
	}
	my $expr2 = $self->deparse($kids[$i], (@kids != 1)/2);
	$expr2 =~ s/^sub :(?!:)/+sub :/; # statement label otherwise
	$expr .= $expr2;
	$callback->($expr, $i);
    }
}

# 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 $raw = shift;
#Carp::confess() unless ref($gv) eq "B::GV";
    my $cv = $gv->FLAGS & SVf_ROK ? $gv->RV : 0;
    my $stash = ($cv || $gv)->STASH->NAME;
    my $name = $raw
	? $cv ? $cv->NAME_HEK || $cv->GV->NAME : $gv->NAME
	: $cv
	    ? B::safename($cv->NAME_HEK || $cv->GV->NAME)
	    : $gv->SAFENAME;
    if ($stash eq 'main' && $name =~ /^::/) {
	$stash = '::';
    }
    elsif (($stash eq 'main'
	    && ($globalnames{$name} || $name =~ /^[^A-Za-z_:]/))
	or ($stash eq $self->{'curstash'} && !$globalnames{$name}
	    && ($stash eq 'main' || $name !~ /::/))
	  )
    {
	$stash = "";
    } else {
	$stash = $stash . "::";
    }
    if (!$raw and $name =~ /^(\^..|{)/) {
        $name = "{$name}";       # ${^WARNING_BITS}, etc and ${
    }
    return $stash . $name;
}

# Return the name to use for a stash variable.
# If a lexical with the same name is in scope, or
# if strictures are enabled, it may need to be
# fully-qualified.
sub stash_variable {
    my ($self, $prefix, $name, $cx) = @_;

    return "$prefix$name" if $name =~ /::/;

    unless ($prefix eq '$' || $prefix eq '@' || $prefix eq '&' || #'
	    $prefix eq '%' || $prefix eq '$#') {
	return "$prefix$name";
    }

    if ($name =~ /^[^[:alpha:]_+-]$/) {
      if (defined $cx && $cx == 26) {
	if ($prefix eq '@') {
	    return "$prefix\{$name}";
	}
	elsif ($name eq '#') { return '${#}' } #  "${#}a" vs "$#a"
      }
      if ($prefix eq '$#') {
	return "\$#{$name}";
      }
    }

    return $prefix . $self->maybe_qualify($prefix, $name);
}

my %unctrl = # portable to EBCDIC
    (
     "\c@" => '@',	# unused
     "\cA" => 'A',
     "\cB" => 'B',
     "\cC" => 'C',
     "\cD" => 'D',
     "\cE" => 'E',
     "\cF" => 'F',
     "\cG" => 'G',
     "\cH" => 'H',
     "\cI" => 'I',
     "\cJ" => 'J',
     "\cK" => 'K',
     "\cL" => 'L',
     "\cM" => 'M',
     "\cN" => 'N',
     "\cO" => 'O',
     "\cP" => 'P',
     "\cQ" => 'Q',
     "\cR" => 'R',
     "\cS" => 'S',
     "\cT" => 'T',
     "\cU" => 'U',
     "\cV" => 'V',
     "\cW" => 'W',
     "\cX" => 'X',
     "\cY" => 'Y',
     "\cZ" => 'Z',
     "\c[" => '[',	# unused
     "\c\\" => '\\',	# unused
     "\c]" => ']',	# unused
     "\c_" => '_',	# unused
    );

# Return just the name, without the prefix.  It may be returned as a quoted
# string.  The second return value is a boolean indicating that.
sub stash_variable_name {
    my($self, $prefix, $gv) = @_;
    my $name = $self->gv_name($gv, 1);
    $name = $self->maybe_qualify($prefix,$name);
    if ($name =~ /^(?:\S|(?!\d)[\ca-\cz]?(?:\w|::)*|\d+)\z/) {
	$name =~ s/^([\ca-\cz])/'^' . $unctrl{$1}/e;
	$name =~ /^(\^..|{)/ and $name = "{$name}";
	return $name, 0; # not quoted
    }
    else {
	single_delim("q", "'", $name, $self), 1;
    }
}

sub maybe_qualify {
    my ($self,$prefix,$name) = @_;
    my $v = ($prefix eq '$#' ? '@' : $prefix) . $name;
    return $name if !$prefix || $name =~ /::/;
    return $self->{'curstash'}.'::'. $name
	if
	    $name =~ /^(?!\d)\w/         # alphabetic
	 && $v    !~ /^\$[ab]\z/	 # not $a or $b
	 && !$globalnames{$name}         # not a global name
	 && $self->{hints} & $strict_bits{vars}  # strict vars
	 && !$self->lex_in_scope($v,1)   # no "our"
      or $self->lex_in_scope($v);        # conflicts with "my" variable
    return $name;
}

sub lex_in_scope {
    my ($self, $name, $our) = @_;
    substr $name, 0, 0, = $our ? 'o' : 'm'; # our/my
    $self->populate_curcvlex() if !defined $self->{'curcvlex'};

    return 0 if !defined($self->{'curcop'});
    my $seq = $self->{'curcop'}->cop_seq;
    return 0 if !exists $self->{'curcvlex'}{$name};
    for my $a (@{$self->{'curcvlex'}{$name}}) {
	my ($st, $en) = @$a;
	return 1 if $seq > $st && $seq <= $en;
    }
    return 0;
}

sub populate_curcvlex {
    my $self = shift;
    for (my $cv = $self->{'curcv'}; class($cv) eq "CV"; $cv = $cv->OUTSIDE) {
	my $padlist = $cv->PADLIST;
	# an undef CV still in lexical chain
	next if class($padlist) eq "SPECIAL";
	my @padlist = $padlist->ARRAY;
	my @ns = $padlist[0]->ARRAY;

	for (my $i=0; $i<@ns; ++$i) {
	    next if class($ns[$i]) eq "SPECIAL";
	    if (class($ns[$i]) eq "PV") {
		# Probably that pesky lexical @_
		next;
	    }
            my $name = $ns[$i]->PVX;
	    next unless defined $name;
	    my ($seq_st, $seq_en) =
		($ns[$i]->FLAGS & SVf_FAKE)
		    ? (0, 999999)
		    : ($ns[$i]->COP_SEQ_RANGE_LOW, $ns[$i]->COP_SEQ_RANGE_HIGH);

	    push @{$self->{'curcvlex'}{
			($ns[$i]->FLAGS & SVpad_OUR ? 'o' : 'm') . $name
		  }}, [$seq_st, $seq_en, $ns[$i]];
	}
    }
}

sub find_scope_st { ((find_scope(@_))[0]); }
sub find_scope_en { ((find_scope(@_))[1]); }

# Recurses down the tree, looking for pad variable introductions and COPs
sub find_scope {
    my ($self, $op, $scope_st, $scope_en) = @_;
    carp("Undefined op in find_scope") if !defined $op;
    return ($scope_st, $scope_en) unless $op->flags & OPf_KIDS;

    my @queue = ($op);
    while(my $op = shift @queue ) {
	for (my $o=$op->first; $$o; $o=$o->sibling) {
	    if ($o->name =~ /^pad.v$/ && $o->private & OPpLVAL_INTRO) {
		my $s = int($self->padname_sv($o->targ)->COP_SEQ_RANGE_LOW);
		my $e = $self->padname_sv($o->targ)->COP_SEQ_RANGE_HIGH;
		$scope_st = $s if !defined($scope_st) || $s < $scope_st;
		$scope_en = $e if !defined($scope_en) || $e > $scope_en;
		return ($scope_st, $scope_en);
	    }
	    elsif (is_state($o)) {
		my $c = $o->cop_seq;
		$scope_st = $c if !defined($scope_st) || $c < $scope_st;
		$scope_en = $c if !defined($scope_en) || $c > $scope_en;
		return ($scope_st, $scope_en);
	    }
	    elsif ($o->flags & OPf_KIDS) {
		unshift (@queue, $o);
	    }
	}
    }

    return ($scope_st, $scope_en);
}

# Returns a list of subs which should be inserted before the COP
sub cop_subs {
    my ($self, $op, $out_seq) = @_;
    my $seq = $op->cop_seq;
    if ($] < 5.021006) {
      # If we have nephews, then our sequence number indicates
      # the cop_seq of the end of some sort of scope.
      if (class($op->sibling) ne "NULL" && $op->sibling->flags & OPf_KIDS
	and my $nseq = $self->find_scope_st($op->sibling) ) {
	$seq = $nseq;
      }
    }
    $seq = $out_seq if defined($out_seq) && $out_seq < $seq;
    return $self->seq_subs($seq);
}

sub seq_subs {
    my ($self, $seq) = @_;
    my @text;
#push @text, "# ($seq)\n";

    return "" if !defined $seq;
    my @pending;
    while (scalar(@{$self->{'subs_todo'}})
	   and $seq > $self->{'subs_todo'}[0][0]) {
	my $cv = $self->{'subs_todo'}[0][1];
	# Skip the OUTSIDE check for lexical subs.  We may be deparsing a
	# cloned anon sub with lexical subs declared in it, in which case
	# the OUTSIDE pointer points to the anon protosub.
	my $lexical = ref $self->{'subs_todo'}[0][3];
	my $outside = !$lexical && $cv && $cv->OUTSIDE;
	if (!$lexical and $cv
	 and ${$cv->OUTSIDE || \0} != ${$self->{'curcv'}})
	{
	    push @pending, shift @{$self->{'subs_todo'}};
	    next;
	}
	push @text, $self->next_todo;
    }
    unshift @{$self->{'subs_todo'}}, @pending;
    return @text;
}

sub _features_from_bundle {
    my ($hints, $hh) = @_;
    foreach (@{$feature::feature_bundle{@feature::hint_bundles[$hints >> $feature::hint_shift]}}) {
	$hh->{$feature::feature{$_}} = 1;
    }
    return $hh;
}

# generate any pragmas, 'package foo' etc needed to synchronise
# with the given cop

sub pragmata {
    my $self = shift;
    my($op) = @_;

    my @text;

    my $stash = $op->stashpv;
    if ($stash ne $self->{'curstash'}) {
	push @text, $self->keyword("package") . " $stash;\n";
	$self->{'curstash'} = $stash;
    }

    if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) {
	push @text, '$[ = '. $op->arybase .";\n";
	$self->{'arybase'} = $op->arybase;
    }

    my $warnings = $op->warnings;
    my $warning_bits;
    if ($warnings->isa("B::SPECIAL") && $$warnings == 4) {
	$warning_bits = $warnings::Bits{"all"} & WARN_MASK;
    }
    elsif ($warnings->isa("B::SPECIAL") && $$warnings == 5) {
        $warning_bits = $warnings::NONE;
    }
    elsif ($warnings->isa("B::SPECIAL")) {
	$warning_bits = undef;
    }
    else {
	$warning_bits = $warnings->PV & WARN_MASK;
    }

    if (defined ($warning_bits) and
       !defined($self->{warnings}) || $self->{'warnings'} ne $warning_bits) {
	push @text,
	    $self->declare_warnings($self->{'warnings'}, $warning_bits);
	$self->{'warnings'} = $warning_bits;
    }

    my $hints = $] < 5.008009 ? $op->private : $op->hints;
    my $old_hints = $self->{'hints'};
    if ($self->{'hints'} != $hints) {
	push @text, $self->declare_hints($self->{'hints'}, $hints);
	$self->{'hints'} = $hints;
    }

    my $newhh;
    if ($] > 5.009) {
	$newhh = $op->hints_hash->HASH;
    }

    if ($] >= 5.015006) {
	# feature bundle hints
	my $from = $old_hints & $feature::hint_mask;
	my $to   = $    hints & $feature::hint_mask;
	if ($from != $to) {
	    if ($to == $feature::hint_mask) {
		if ($self->{'hinthash'}) {
		    delete $self->{'hinthash'}{$_}
			for grep /^feature_/, keys %{$self->{'hinthash'}};
		}
		else { $self->{'hinthash'} = {} }
		$self->{'hinthash'}
		    = _features_from_bundle($from, $self->{'hinthash'});
	    }
	    else {
		my $bundle =
		    $feature::hint_bundles[$to >> $feature::hint_shift];
		$bundle =~ s/(\d[13579])\z/$1+1/e; # 5.11 => 5.12
		push @text,
		    $self->keyword("no") . " feature ':all';\n",
		    $self->keyword("use") . " feature ':$bundle';\n";
	    }
	}
    }

    if ($] > 5.009) {
	push @text, $self->declare_hinthash(
	    $self->{'hinthash'}, $newhh,
	    $self->{indent_size}, $self->{hints},
	);
	$self->{'hinthash'} = $newhh;
    }

    return join("", @text);
}


# Notice how subs and formats are inserted between statements here;
# also $[ assignments and pragmas.
sub pp_nextstate {
    my $self = shift;
    my($op, $cx) = @_;
    $self->{'curcop'} = $op;

    my @text;

    my @subs = $self->cop_subs($op);
    if (@subs) {
	# Special marker to swallow up the semicolon
	push @subs, "\cK";
    }
    push @text, @subs;

    push @text, $self->pragmata($op);


    # This should go after of any branches that add statements, to
    # increase the chances that it refers to the same line it did in
    # the original program.
    if ($self->{'linenums'} && $cx != .5) { # $cx == .5 means in a format
	push @text, "\f#line " . $op->line .
	  ' "' . $op->file, qq'"\n';
    }

    push @text, $op->label . ": " if $op->label;

    return join("", @text);
}

sub declare_warnings {
    my ($self, $from, $to) = @_;
    if (($to & WARN_MASK) eq (warnings::bits("all") & WARN_MASK)) {
	return $self->keyword("use") . " warnings;\n";
    }
    elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
	return $self->keyword("no") . " warnings;\n";
    }
    return "BEGIN {\${^WARNING_BITS} = \""
           . join("", map { sprintf("\\x%02x", ord $_) } split "", $to)
           . "\"}\n\cK";
}

sub declare_hints {
    my ($self, $from, $to) = @_;
    my $use = $to   & ~$from;
    my $no  = $from & ~$to;
    my $decls = "";
    for my $pragma (hint_pragmas($use)) {
	$decls .= $self->keyword("use") . " $pragma;\n";
    }
    for my $pragma (hint_pragmas($no)) {
        $decls .= $self->keyword("no") . " $pragma;\n";
    }
    return $decls;
}

# Internal implementation hints that the core sets automatically, so don't need
# (or want) to be passed back to the user
my %ignored_hints = (
    'open<' => 1,
    'open>' => 1,
    ':'     => 1,
    'strict/refs' => 1,
    'strict/subs' => 1,
    'strict/vars' => 1,
);

my %rev_feature;

sub declare_hinthash {
    my ($self, $from, $to, $indent, $hints) = @_;
    my $doing_features =
	($hints & $feature::hint_mask) == $feature::hint_mask;
    my @decls;
    my @features;
    my @unfeatures; # bugs?
    for my $key (sort keys %$to) {
	next if $ignored_hints{$key};
	my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
	next if $is_feature and not $doing_features;
	if (!exists $from->{$key} or $from->{$key} ne $to->{$key}) {
	    push(@features, $key), next if $is_feature;
	    push @decls,
		qq(\$^H{) . single_delim("q", "'", $key, $self) . qq(} = )
	      . (
		   defined $to->{$key}
			? single_delim("q", "'", $to->{$key}, $self)
			: 'undef'
		)
	      . qq(;);
	}
    }
    for my $key (sort keys %$from) {
	next if $ignored_hints{$key};
	my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
	next if $is_feature and not $doing_features;
	if (!exists $to->{$key}) {
	    push(@unfeatures, $key), next if $is_feature;
	    push @decls, qq(delete \$^H{'$key'};);
	}
    }
    my @ret;
    if (@features || @unfeatures) {
	if (!%rev_feature) { %rev_feature = reverse %feature::feature }
    }
    if (@features) {
	push @ret, $self->keyword("use") . " feature "
		 . join(", ", map "'$rev_feature{$_}'", @features) . ";\n";
    }
    if (@unfeatures) {
	push @ret, $self->keyword("no") . " feature "
		 . join(", ", map "'$rev_feature{$_}'", @unfeatures)
		 . ";\n";
    }
    @decls and
	push @ret,
	     join("\n" . (" " x $indent), "BEGIN {", @decls) . "\n}\n\cK";
    return @ret;
}

sub hint_pragmas {
    my ($bits) = @_;
    my (@pragmas, @strict);
    push @pragmas, "integer" if $bits & 0x1;
    for (sort keys %strict_bits) {
	push @strict, "'$_'" if $bits & $strict_bits{$_};
    }
    if (@strict == keys %strict_bits) {
	push @pragmas, "strict";
    }
    elsif (@strict) {
	push @pragmas, "strict " . join ', ', @strict;
    }
    push @pragmas, "bytes" if $bits & 0x8;
    return @pragmas;
}

sub pp_dbstate { pp_nextstate(@_) }
sub pp_setstate { pp_nextstate(@_) }

sub pp_unstack { return "" } # see also leaveloop

my %feature_keywords = (
  # keyword => 'feature',
    state   => 'state',
    say     => 'say',
    given   => 'switch',
    when    => 'switch',
    default => 'switch',
    break   => 'switch',
    evalbytes=>'evalbytes',
    __SUB__ => '__SUB__',
   fc       => 'fc',
);

# keywords that are strong and also have a prototype
#
my %strong_proto_keywords = map { $_ => 1 } qw(
    pos
    prototype
    scalar
    study
    undef
);

sub feature_enabled {
	my($self,$name) = @_;
	my $hh;
	my $hints = $self->{hints} & $feature::hint_mask;
	if ($hints && $hints != $feature::hint_mask) {
	    $hh = _features_from_bundle($hints);
	}
	elsif ($hints) { $hh = $self->{'hinthash'} }
	return $hh && $hh->{"feature_$feature_keywords{$name}"}
}

sub keyword {
    my $self = shift;
    my $name = shift;
    return $name if $name =~ /^CORE::/; # just in case
    if (exists $feature_keywords{$name}) {
	return "CORE::$name" if not $self->feature_enabled($name);
    }
    # This sub may be called for a program that has no nextstate ops.  In
    # that case we may have a lexical sub named no/use/sub in scope but
    # but $self->lex_in_scope will return false because it depends on the
    # current nextstate op.  So we need this alternate method if there is
    # no current cop.
    if (!$self->{'curcop'}) {
	$self->populate_curcvlex() if !defined $self->{'curcvlex'};
	return "CORE::$name" if exists $self->{'curcvlex'}{"m&$name"}
			     || exists $self->{'curcvlex'}{"o&$name"};
    } elsif ($self->lex_in_scope("&$name")
	  || $self->lex_in_scope("&$name", 1)) {
	return "CORE::$name";
    }
    if ($strong_proto_keywords{$name}
        || ($name !~ /^(?:chom?p|do|exec|glob|s(?:elect|ystem))\z/
	    && !defined eval{prototype "CORE::$name"})
    ) { return $name }
    if (
	exists $self->{subs_declared}{$name}
	 or
	exists &{"$self->{curstash}::$name"}
    ) {
	return "CORE::$name"
    }
    return $name;
}

sub baseop {
    my $self = shift;
    my($op, $cx, $name) = @_;
    return $self->keyword($name);
}

sub pp_stub { "()" }
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"
				   # avoid confusion with filetests
				 : $name eq '-'
				   && $kid =~ /^[a-zA-Z](?!\w)/
					? "$name($kid)"
					: "$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) }
*pp_ncomplement = *pp_complement;
sub pp_scomplement { 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->listop($op, $cx, "not", $op->first);
    } else {
	$self->pfixop($op, $cx, "!", 21);	
    }
}

sub unop {
    my $self = shift;
    my($op, $cx, $name, $nollafr) = @_;
    my $kid;
    if ($op->flags & OPf_KIDS) {
	$kid = $op->first;
 	if (not $name) {
 	    # this deals with 'boolkeys' right now
 	    return $self->deparse($kid,$cx);
 	}
	my $builtinname = $name;
	$builtinname =~ /^CORE::/ or $builtinname = "CORE::$name";
	if (defined prototype($builtinname)
	   && $builtinname ne 'CORE::readline'
	   && prototype($builtinname) =~ /^;?\*/
	   && $kid->name eq "rv2gv") {
	    $kid = $kid->first;
	}

	if ($nollafr) {
	    if (($kid = $self->deparse($kid, 16)) !~ s/^\cS//) {
		# require foo() is a syntax error.
		$kid =~ /^(?!\d)\w/ and $kid = "($kid)";
	    }
	    return $self->maybe_parens(
			$self->keyword($name) . " $kid", $cx, 16
		   );
	}   
	return $self->maybe_parens_unop($name, $kid, $cx);
    } else {
	return $self->maybe_parens(
	    $self->keyword($name) . ($op->flags & OPf_SPECIAL ? "()" : ""),
	    $cx, 16,
	);
    }
}

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") }
{ no strict 'refs'; *{"pp_r$_"} = *{"pp_$_"} for qw< keys each values >; }
sub pp_boolkeys { 
    # no name because its an optimisation op that has no keyword
    unop(@_,"");
}
sub pp_aeach { unop(@_, "each") }
sub pp_avalues { unop(@_, "values") }
sub pp_akeys { 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 {
    my ($self, $op, $cx) = @_;
    if (($op->flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS)) {
	my $kw = $self->keyword("chdir");
	my $kid = $self->const_sv($op->first)->PV;
	my $code = $kw
		 . ($cx >= 16 || $self->{'parens'} ? "($kid)" : " $kid");
	maybe_targmy(@_, sub { $_[3] }, $code);
    } else {
	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 {
    my $code = unop(@_, "do", 1); # llafr does not apply
    if ($code =~ s/^((?:CORE::)?do) \{/$1({/) { $code .= ')' }
    $code;
}
sub pp_entereval {
    unop(
      @_,
      $_[1]->private & OPpEVAL_BYTES ? 'evalbytes' : "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_continue { unop(@_, "continue"); }
sub pp_break { unop(@_, "break"); }

sub givwhen {
    my $self = shift;
    my($op, $cx, $givwhen) = @_;

    my $enterop = $op->first;
    my ($head, $block);
    if ($enterop->flags & OPf_SPECIAL) {
	$head = $self->keyword("default");
	$block = $self->deparse($enterop->first, 0);
    }
    else {
	my $cond = $enterop->first;
	my $cond_str = $self->deparse($cond, 1);
	$head = "$givwhen ($cond_str)";
	$block = $self->deparse($cond->sibling, 0);
    }

    return "$head {\n".
	"\t$block\n".
	"\b}\cK";
}

sub pp_leavegiven { givwhen(@_, $_[0]->keyword("given")); }
sub pp_leavewhen  { givwhen(@_, $_[0]->keyword("when")); }

sub pp_exists {
    my $self = shift;
    my($op, $cx) = @_;
    my $arg;
    my $name = $self->keyword("exists");
    if ($op->private & OPpEXISTS_SUB) {
	# Checking for the existence of a subroutine
	return $self->maybe_parens_func($name,
				$self->pp_rv2cv($op->first, 16), $cx, 16);
    }
    if ($op->flags & OPf_SPECIAL) {
	# Array element, not hash element
	return $self->maybe_parens_func($name,
				$self->pp_aelem($op->first, 16), $cx, 16);
    }
    return $self->maybe_parens_func($name, $self->pp_helem($op->first, 16),
				    $cx, 16);
}

sub pp_delete {
    my $self = shift;
    my($op, $cx) = @_;
    my $arg;
    my $name = $self->keyword("delete");
    if ($op->private & OPpSLICE) {
	if ($op->flags & OPf_SPECIAL) {
	    # Deleting from an array, not a hash
	    return $self->maybe_parens_func($name,
					$self->pp_aslice($op->first, 16),
					$cx, 16);
	}
	return $self->maybe_parens_func($name,
					$self->pp_hslice($op->first, 16),
					$cx, 16);
    } else {
	if ($op->flags & OPf_SPECIAL) {
	    # Deleting from an array, not a hash
	    return $self->maybe_parens_func($name,
					$self->pp_aelem($op->first, 16),
					$cx, 16);
	}
	return $self->maybe_parens_func($name,
					$self->pp_helem($op->first, 16),
					$cx, 16);
    }
}

sub pp_require {
    my $self = shift;
    my($op, $cx) = @_;
    my $opname = $op->flags & OPf_SPECIAL ? 'CORE::require' : 'require';
    my $kid = $op->first;
    if ($kid->name eq 'const') {
	my $priv = $kid->private;
	my $sv = $self->const_sv($kid);
	my $arg;
	if ($priv & OPpCONST_BARE) {
	    $arg = $sv->PV;
	    $arg =~ s[/][::]g;
	    $arg =~ s/\.pm//g;
	} elsif ($priv & OPpCONST_NOVER) {
	    $opname = $self->keyword('no');
	    $arg = $self->const($sv, 16);
	} elsif ((my $tmp = $self->const($sv, 16)) =~ /^v/) {
	    $arg = $tmp;
	}
	if ($arg) {
	    return $self->maybe_parens("$opname $arg", $cx, 16);
	}
    }
    $self->unop(
	    $op, $cx,
	    $opname,
	    1, # llafr does not apply
    );
}

sub pp_scalar {
    my $self = shift;
    my($op, $cx) = @_;
    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;
    return $self->{'curcv'}->PADLIST->ARRAYelt(1)->ARRAYelt($targ);
}

sub anon_hash_or_list {
    my $self = shift;
    my($op, $cx) = @_;

    my($pre, $post) = @{{"anonlist" => ["[","]"],
			 "anonhash" => ["{","}"]}->{$op->name}};
    my($expr, @exprs);
    $op = $op->first->sibling; # skip pushmark
    for (; !null($op); $op = $op->sibling) {
	$expr = $self->deparse($op, 6);
	push @exprs, $expr;
    }
    if ($pre eq "{" and $cx < 1) {
	# Disambiguate that it's not a block
	$pre = "+{";
    }
    return $pre . join(", ", @exprs) . $post;
}

sub pp_anonlist {
    my $self = shift;
    my ($op, $cx) = @_;
    if ($op->flags & OPf_SPECIAL) {
	return $self->anon_hash_or_list($op, $cx);
    }
    warn "Unexpected op pp_" . $op->name() . " without OPf_SPECIAL";
    return 'XXX';
}

*pp_anonhash = \&pp_anonlist;

sub pp_refgen {
    my $self = shift;	
    my($op, $cx) = @_;
    my $kid = $op->first;
    if ($kid->name eq "null") {
	my $anoncode = $kid = $kid->first;
	if ($anoncode->name eq "anonconst") {
	    $anoncode = $anoncode->first->first->sibling;
	}
	if ($anoncode->name eq "anoncode"
	 or !null($anoncode = $kid->sibling) and
		 $anoncode->name eq "anoncode") {
            return $self->e_anoncode({ code => $self->padval($anoncode->targ) });
	} elsif ($kid->name eq "pushmark") {
            my $sib_name = $kid->sibling->name;
            if ($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";
            }
        }
    }
    local $self->{'in_refgen'} = 1;
    $self->pfixop($op, $cx, "\\", 20);
}

sub e_anoncode {
    my ($self, $info) = @_;
    my $text = $self->deparse_sub($info->{code});
    return $self->keyword("sub") . " $text";
}

sub pp_srefgen { pp_refgen(@_) }

sub pp_readline {
    my $self = shift;
    my($op, $cx) = @_;
    my $kid = $op->first;
    if (is_scalar($kid)
        and $op->flags & OPf_SPECIAL
        and $self->deparse($kid, 1) eq 'ARGV')
    {
        return '<<>>';
    }
    return $self->unop($op, $cx, "readline");
}

sub pp_rcatline {
    my $self = shift;
    my($op) = @_;
    return "<" . $self->gv_name($self->gv_or_padgv($op)) . ">";
}

# 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 pp_fc { dq_unop(@_, "fc") }

sub loopex {
    my $self = shift;
    my ($op, $cx, $name) = @_;
    if (class($op) eq "PVOP") {
	$name .= " " . $op->pv;
    } elsif (class($op) eq "OP") {
	# no-op
    } elsif (class($op) eq "UNOP") {
	(my $kid = $self->deparse($op->first, 7)) =~ s/^\cS//;
	# last foo() is a syntax error.
	$kid =~ /^(?!\d)\w/ and $kid = "($kid)";
	$name .= " $kid";
    }
    return $self->maybe_parens($name, $cx, 7);
}

sub pp_last { loopex(@_, "last") }
sub pp_next { loopex(@_, "next") }
sub pp_redo { loopex(@_, "redo") }
sub pp_goto { loopex(@_, "goto") }
sub pp_dump { loopex(@_, "CORE::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()
	if ($name =~ /^-/) {
	    (my $kid = $self->deparse($op->first, 16)) =~ s/^\cS//;
	    return $self->maybe_parens("$name $kid", $cx, 16);
	}
	return $self->maybe_parens_unop($name, $op->first, $cx);
    } elsif (class($op) =~ /^(SV|PAD)OP$/) {
	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(@_, "-w") }
sub pp_fteexec  { ftst(@_, "-x") }
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
sub LIST_CONTEXT () { 4 } # Assignment is in list context

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, 'nbit_and' => 13, 'sbit_and' => 13,
	     'bit_or' => 12, 'bit_xor' => 12,
	     'sbit_or' => 12, 'sbit_xor' => 12,
	     'nbit_or' => 12, 'nbit_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, 'refassign' => 7, 'refassign=' => 7,
	      'add=' => 7, 'i_add=' => 7,
	      'subtract=' => 7, 'i_subtract=' => 7,
	      'concat=' => 7,
	      'left_shift=' => 7, 'right_shift=' => 7,
	      'bit_and=' => 7, 'sbit_and=' => 7, 'nbit_and=' => 7,
	      'nbit_or=' => 7, 'nbit_xor=' => 7,
	      'sbit_or=' => 7, 'sbit_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);
    }
    my $leftop = $left;
    $left = $self->deparse_binop_left($op, $left, $prec);
    $left = "($left)" if $flags & LIST_CONTEXT
		     and    $left !~ /^(my|our|local|)[\@\(]/
			 || do {
				# Parenthesize if the left argument is a
				# lone repeat op.
				my $left = $leftop->first->sibling;
				$left->name eq 'repeat'
				    && null($left->sibling);
			    };
    $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) }
*pp_nbit_and = *pp_bit_and;
*pp_nbit_or  = *pp_bit_or;
*pp_nbit_xor = *pp_bit_xor;
sub pp_sbit_and { maybe_targmy(@_, \&binop, "&.", 13, ASSIGN) }
sub pp_sbit_or { maybe_targmy(@_, \&binop, "|.", 12, ASSIGN) }
sub pp_sbit_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 { maybe_targmy(@_, \&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 { maybe_targmy(@_, \&binop, "cmp", 14) }

sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }
sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN | LIST_CONTEXT) }

sub pp_smartmatch {
    my ($self, $op, $cx) = @_;
    if ($op->flags & OPf_SPECIAL) {
	return $self->deparse($op->last, $cx);
    }
    else {
	binop(@_, "~~", 14);
    }
}

# '.' 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);
}

sub pp_repeat { maybe_targmy(@_, \&repeat) }

# 'x' is weird when the left arg is a list
sub 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
			# in 5.21.5 and earlier
	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 {
	my $dolist = $op->private & OPpREPEAT_DOLIST;
	$left = $self->deparse_binop_left($op, $left, $dolist ? 1 : $prec);
	if ($dolist) {
	    $left = "($left)";
	}
    }
    $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;
    $blockname &&= $self->keyword($blockname);
    if ($cx < 1 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 < 1 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") }
sub pp_dor { logop(@_, "//", 10) }

# 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 pp_dorassign { logassignop(@_, "//=") }

sub rv2gv_or_string {
    my($self,$op) = @_;
    if ($op->name eq "gv") { # could be open("open") or open("###")
	my($name,$quoted) =
	    $self->stash_variable_name("", $self->gv_or_padgv($op));
	$quoted ? $name : "*$name";
    }
    else {
	$self->deparse($op, 6);
    }
}

sub listop {
    my $self = shift;
    my($op, $cx, $name, $kid, $nollafr) = @_;
    my(@exprs);
    my $parens = ($cx >= 5) || $self->{'parens'};
    $kid ||= $op->first->sibling;
    # If there are no arguments, add final parentheses (or parenthesize the
    # whole thing if the llafr does not apply) to account for cases like
    # (return)+1 or setpgrp()+1.  When the llafr does not apply, we use a
    # precedence of 6 (< comma), as "return, 1" does not need parentheses.
    if (null $kid) {
	return $nollafr
		? $self->maybe_parens($self->keyword($name), $cx, 7)
		: $self->keyword($name) . '()' x (7 < $cx);
    }
    my $first;
    my $fullname = $self->keyword($name);
    my $proto = prototype("CORE::$name");
    if (
	 (     (defined $proto && $proto =~ /^;?\*/)
	    || $name eq 'select' # select(F) doesn't have a proto
	 )
	 && $kid->name eq "rv2gv"
	 && !($kid->private & OPpLVAL_INTRO)
    ) {
	$first = $self->rv2gv_or_string($kid->first);
    }
    else {
	$first = $self->deparse($kid, 6);
    }
    if ($name eq "chmod" && $first =~ /^\d+$/) {
	$first = sprintf("%#o", $first);
    }
    $first = "+$first"
	if not $parens and not $nollafr and substr($first, 0, 1) eq "(";
    push @exprs, $first;
    $kid = $kid->sibling;
    if (defined $proto && $proto =~ /^\*\*/ && $kid->name eq "rv2gv"
	 && !($kid->private & OPpLVAL_INTRO)) {
	push @exprs, $first = $self->rv2gv_or_string($kid->first);
	$kid = $kid->sibling;
    }
    for (; !null($kid); $kid = $kid->sibling) {
	push @exprs, $self->deparse($kid, 6);
    }
    if ($name eq "reverse" && ($op->private & OPpREVERSE_INPLACE)) {
	return "$exprs[0] = $fullname"
	         . ($parens ? "($exprs[0])" : " $exprs[0]");
    }

    if ($parens && $nollafr) {
	return "($fullname " . join(", ", @exprs) . ")";
    } elsif ($parens) {
	return "$fullname(" . join(", ", @exprs) . ")";
    } else {
	return "$fullname " . join(", ", @exprs);
    }
}

sub pp_bless { listop(@_, "bless") }
sub pp_atan2 { maybe_targmy(@_, \&listop, "atan2") }
sub pp_substr {
    my ($self,$op,$cx) = @_;
    if ($op->private & OPpSUBSTR_REPL_FIRST) {
	return
	   listop($self, $op, 7, "substr", $op->first->sibling->sibling)
	 . " = "
	 . $self->deparse($op->first->sibling, 7);
    }
    maybe_local(@_, listop(@_, "substr"))
}
sub pp_vec { maybe_targmy(@_, \&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") }
sub pp_return { listop(@_, "return", undef, 1) } # llafr does not apply
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(@_, "socketpair") }
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(@_, \&indirop, "system") }
sub pp_exec { maybe_targmy(@_, \&indirop, "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 $kid = $op->first->sibling;  # skip pushmark
    my $keyword =
	$op->flags & OPf_SPECIAL ? 'glob' : $self->keyword('glob');
    my $text = $self->deparse($kid);
    return $cx >= 5 || $self->{'parens'}
	? "$keyword($text)"
	: "$keyword $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);
    my $name = $self->keyword('truncate');
    if ($parens) {
	return "$name($fh, $len)";
    } else {
	return "$name $fh, $len";
    }
}

sub indirop {
    my $self = shift;
    my($op, $cx, $name) = @_;
    my($expr, @exprs);
    my $firstkid = 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) . "}";
	    $indir = "{;}" if $indir eq "{}";
	} elsif ($indir->name eq "const" && $indir->private & OPpCONST_BARE) {
	    $indir = $self->const_sv($indir)->PV;
	} else {
	    $indir = $self->deparse($indir, 24);
	}
	$indir = $indir . " ";
	$kid = $kid->sibling;
    }
    if ($name eq "sort" && $op->private & (OPpSORT_NUMERIC | OPpSORT_INTEGER)) {
	$indir = ($op->private & OPpSORT_DESCEND) ? '{$b <=> $a} '
						  : '{$a <=> $b} ';
    }
    elsif ($name eq "sort" && $op->private & OPpSORT_DESCEND) {
	$indir = '{$b cmp $a} ';
    }
    for (; !null($kid); $kid = $kid->sibling) {
	$expr = $self->deparse($kid, !$indir && $kid == $firstkid && $name eq "sort" && $firstkid->name eq "entersub" ? 16 : 6);
	push @exprs, $expr;
    }
    my $name2;
    if ($name eq "sort" && $op->private & OPpSORT_REVERSE) {
	$name2 = $self->keyword('reverse') . ' ' . $self->keyword('sort');
    }
    else { $name2 = $self->keyword($name) }
    if ($name eq "sort" && ($op->private & OPpSORT_INPLACE)) {
	return "$exprs[0] = $name2 $indir $exprs[0]";
    }

    my $args = $indir . join(", ", @exprs);
    if ($indir ne "" && $name eq "sort") {
	# We don't want to say "sort(f 1, 2, 3)", since perl -w will
	# give bareword warnings in that case. Therefore if context
	# requires, we'll put parens around the outside "(sort f 1, 2,
	# 3)". Unfortunately, we'll currently think the parens are
	# necessary more often that they really are, because we don't
	# distinguish which side of an assignment we're on.
	if ($cx >= 5) {
	    return "($name2 $args)";
	} else {
	    return "$name2 $args";
	}
    } elsif (
	!$indir && $name eq "sort"
      && !null($op->first->sibling)
      && $op->first->sibling->name eq 'entersub'
    ) {
	# We cannot say sort foo(bar), as foo will be interpreted as a
	# comparison routine.  We have to say sort(...) in that case.
	return "$name2($args)";
    } else {
	return length $args
		? $self->maybe_parens_func($name2, $args, $cx, 5)
		: $name2 . '()' x (7 < $cx);
    }

}

sub pp_prtf { indirop(@_, "printf") }
sub pp_print { indirop(@_, "print") }
sub pp_say  { indirop(@_, "say") }
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);
	$code .= ", " if !null($kid->sibling);
    }
    $kid = $kid->sibling;
    for (; !null($kid); $kid = $kid->sibling) {
	$expr = $self->deparse($kid, 6);
	push @exprs, $expr if defined $expr;
    }
    return $self->maybe_parens_func($self->keyword($name),
				    $code . join(", ", @exprs), $cx, 5);
}

sub pp_mapwhile { mapop(@_, "map") }
sub pp_grepwhile { mapop(@_, "grep") }
sub pp_mapstart { baseop(@_, "map") }
sub pp_grepstart { baseop(@_, "grep") }

my %uses_intro;
BEGIN {
    @uses_intro{
	eval { require B::Op_private }
	  ? @{$B::Op_private::ops_using{OPpLVAL_INTRO}}
	  : qw(gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice
	       hslice delete padsv padav padhv enteriter entersub padrange
	       pushmark cond_expr refassign list)
    } = ();
    delete @uses_intro{qw( lvref lvrefslice lvavref entersub )};
}

sub pp_list {
    my $self = shift;
    my($op, $cx) = @_;
    my($expr, @exprs);
    my $kid = $op->first->sibling; # skip pushmark
    return '' if class($kid) eq 'NULL';
    my $lop;
    my $local = "either"; # could be local(...), my(...), state(...) or our(...)
    my $type;
    for ($lop = $kid; !null($lop); $lop = $lop->sibling) {
	my $lopname = $lop->name;
	my $loppriv = $lop->private;
	my $newtype;
	if ($lopname =~ /^pad[ash]v$/ && $loppriv & OPpLVAL_INTRO) {
	    if ($loppriv & OPpPAD_STATE) { # state()
		($local = "", last) if $local !~ /^(?:either|state)$/;
		$local = "state";
	    } else { # my()
		($local = "", last) if $local !~ /^(?:either|my)$/;
		$local = "my";
	    }
	    my $padname = $self->padname_sv($lop->targ);
	    if ($padname->FLAGS & SVpad_TYPED) {
		$newtype = $padname->SvSTASH->NAME;
	    }
	} elsif ($lopname =~ /^(?:gv|rv2)([ash])v$/
			&& $loppriv & OPpOUR_INTRO
		or $lopname eq "null" && class($lop) eq 'UNOP'
			&& $lop->first->name eq "gvsv"
			&& $lop->first->private & OPpOUR_INTRO) { # our()
	    my $newlocal = "local " x !!($loppriv & OPpLVAL_INTRO) . "our";
	    ($local = "", last)
		if $local ne 'either' && $local ne $newlocal;
	    $local = $newlocal;
	    my $funny = !$1 || $1 eq 's' ? '$' : $1 eq 'a' ? '@' : '%';
	    if (my $t = $self->find_our_type(
		    $funny . $self->gv_or_padgv($lop->first)->NAME
	       )) {
		$newtype = $t;
	    }
	} elsif ($lopname ne 'undef'
	   and    !($loppriv & OPpLVAL_INTRO)
	       || !exists $uses_intro{$lopname eq 'null'
					? substr B::ppname($lop->targ), 3
					: $lopname})
	{
	    $local = ""; # or not
	    last;
	} elsif ($lopname ne "undef")
	{
	    # local()
	    ($local = "", last) if $local !~ /^(?:either|local)$/;
	    $local = "local";
	}
	if (defined $type && defined $newtype && $newtype ne $type) {
	    $local = '';
	    last;
	}
	$type = $newtype;
    }
    $local = "" if $local eq "either"; # no point if it's all undefs
    $local &&= join ' ', map $self->keyword($_), split / /, $local;
    $local .= " $type " if $local && length $type;
    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 < 1 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, 6);
	$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 = $self->keyword("if") . " ($cond) {\n\t$true\n\b}";
    my @elsifs;
    my $elsif;
    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
	if ($newcond->name eq "lineseq")
	{
	    # lineseq to ensure correct line numbers in elsif()
	    # Bug #37302 fixed by change #33710.
	    $newcond = $newcond->first->sibling;
	}
	$newcond = $self->deparse($newcond, 1);
	$newtrue = $self->deparse($newtrue, 0);
	$elsif ||= $self->keyword("elsif");
	push @elsifs, "$elsif ($newcond) {\n\t$newtrue\n\b}";
    }
    if (!null($false)) {
	$false = $cuddle . $self->keyword("else") . " {\n\t" .
	  $self->deparse($false, 0) . "\n\b}\cK";
    } else {
	$false = "\cK";
    }
    return $head . join($cuddle, "", @elsifs) . $false;
}

sub pp_once {
    my ($self, $op, $cx) = @_;
    my $cond = $op->first;
    my $true = $cond->sibling;

    my $ret = $self->deparse($true, $cx);
    $ret =~ s/^(\(?)\$/$1 . $self->keyword("state") . ' $'/e;
    $ret;
}

sub loop_common {
    my $self = shift;
    my($op, $cx, $init) = @_;
    my $enter = $op->first;
    my $kid = $enter->sibling;
    local(@$self{qw'curstash warnings hints hinthash'})
		= @$self{qw'curstash warnings hints hinthash'};
    my $head = "";
    my $bare = 0;
    my $body;
    my $cond = undef;
    my $name;
    if ($kid->name eq "lineseq") { # bare or infinite loop
	if ($kid->last->name eq "unstack") { # infinite
	    $head = "while (1) "; # Can't use for(;;) if there's a continue
	    $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 ($ary->name eq 'null' and $enter->private & OPpITER_REVERSED) {
	    # "reverse" was optimised away
	    $ary = listop($self, $ary->first->sibling, 1, 'reverse');
	} elsif ($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) {
            $var = $self->pp_padsv($enter, 1, 1);
	} elsif ($var->name eq "rv2gv") {
	    $var = $self->pp_rv2sv($var, 1);
	    if ($enter->private & OPpOUR_INTRO) {
		# our declarations don't have package names
		$var =~ s/^(.).*::/$1/;
		$var = "our $var";
	    }
	} elsif ($var->name eq "gv") {
	    $var = "\$" . $self->deparse($var, 1);
	} else {
	    $var = $self->deparse($var, 1);
	}
	$body = $kid->first->first->sibling; # skip OP_AND and OP_ITER
	if (!is_state $body->first and $body->first->name !~ /^(?:stub|leave|scope)$/) {
	    confess unless $var eq '$_';
	    $body = $body->first;
	    return $self->deparse($body, 2) . " "
		 . $self->keyword("foreach") . " ($ary)";
	}
	$head = "foreach $var ($ary) ";
    } elsif ($kid->name eq "null") { # while/until
	$kid = $kid->first;
	$name = {"and" => "while", "or" => "until"}->{$kid->name};
	$cond = $kid->first;
	$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 last child, except
    # in a bare loop, when it will point to the leaveloop. When neither of
    # these conditions hold, then the second-to-last child is the continue
    # block (or the last in a bare loop).
    my $cont_start = $enter->nextop;
    my $cont;
    my $precond;
    my $postcond;
    if ($$cont_start != $$op && ${$cont_start} != ${$body->last}) {
	if ($bare) {
	    $cont = $body->last;
	} else {
	    $cont = $body->first;
	    while (!null($cont->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(undef, 0, @states);
	if (defined $cond and not is_scope $cont and $self->{'expand'} < 3) {
	    $precond = "for ($init; ";
	    $postcond = "; " . $self->deparse($cont, 1) .") ";
	    $cont = "\cK";
	} else {
	    $cont = $cuddle . "continue {\n\t" .
	      $self->deparse($cont, 0) . "\n\b}\cK";
	}
    } else {
	return "" if !defined $body;
	if (length $init) {
	    $precond = "for ($init; ";
	    $postcond = ";) ";
	}
	$cont = "\cK";
	$body = $self->deparse($body, 0);
    }
    if ($precond) { # for(;;)
	$cond &&= $name eq 'until'
		    ? listop($self, undef, 1, "not", $cond->first)
		    : $self->deparse($cond, 1);
	$head = "$precond$cond$postcond";
    }
    if ($name && !$head) {
	ref $cond and $cond = $self->deparse($cond, 1);
	$head = "$name ($cond) ";
    }
    $head =~ s/^(for(?:each)?|while|until)/$self->keyword($1)/e;
    $body =~ s/;?$/;\n/;

    return $head . "{\n\t" . $body . "\b}" . $cont;
}

sub pp_leaveloop { shift->loop_common(@_, "") }

sub for_loop {
    my $self = shift;
    my($op, $cx) = @_;
    my $init = $self->deparse($op, 1);
    my $s = $op->sibling;
    my $ll = $s->name eq "unstack" ? $s->sibling : $s->first->sibling;
    return $self->loop_common($ll, $cx, $init);
}

sub pp_leavetry {
    my $self = shift;
    return "eval {\n\t" . $self->pp_leave(@_) . "\n\b}";
}

sub _op_is_or_was {
  my ($op, $expect_type) = @_;
  my $type = $op->type;
  return($type == $expect_type
         || ($type == OP_NULL && $op->targ == $expect_type));
}

sub pp_null {
    my($self, $op, $cx) = @_;
    if (class($op) eq "OP") {
	# old value is lost
	return $self->{'ex_const'} if $op->targ == OP_CONST;
    } elsif (class ($op) eq "COP") {
	    return &pp_nextstate;
    } elsif ($op->first->name eq 'pushmark'
             or $op->first->name eq 'null'
                && $op->first->targ == OP_PUSHMARK
                && _op_is_or_was($op, OP_LIST)) {
	return $self->pp_list($op, $cx);
    } elsif ($op->first->name eq "enter") {
	return $self->pp_leave($op, $cx);
    } elsif ($op->first->name eq "leave") {
	return $self->pp_leave($op->first, $cx);
    } elsif ($op->first->name eq "scope") {
	return $self->pp_scope($op->first, $cx);
    } elsif ($op->targ == OP_STRINGIFY) {
	return $self->dquote($op, $cx);
    } elsif ($op->targ == OP_GLOB) {
	return $self->pp_glob(
	         $op->first    # entersub
	            ->first    # ex-list
	            ->first    # pushmark
	            ->sibling, # glob
	         $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 =~ /^transr?\z/ and
	     $op->first->sibling->flags & OPf_STACKED) {
	return $self->maybe_parens($self->deparse($op->first, 20) . " =~ "
				   . $self->deparse($op->first->sibling, 20),
				   $cx, 20);
    } elsif ($op->flags & OPf_SPECIAL && $cx < 1 && !$op->targ) {
	return ($self->lex_in_scope("&do") ? "CORE::do" : "do")
	     . " {\n\t". $self->deparse($op->first, $cx) ."\n\b};";
    } elsif (!null($op->first->sibling) and
	     $op->first->sibling->name eq "null" and
	     class($op->first->sibling) eq "UNOP" and
	     $op->first->sibling->first->flags & OPf_STACKED and
	     $op->first->sibling->first->name eq "rcatline") {
	return $self->maybe_parens($self->deparse($op->first, 18) . " .= "
				   . $self->deparse($op->first->sibling, 18),
				   $cx, 18);
    } 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, $forbid_parens) = @_;
    my $targ = $op->targ;
    return $self->maybe_my($op, $cx, $self->padname($targ),
			   $self->padname_sv($targ),
			   $forbid_parens);
}

sub pp_padav { pp_padsv(@_) }
sub pp_padhv { pp_padsv(@_) }

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->stash_variable("\$",
				 $self->gv_name($gv), $cx));
}

sub pp_gv {
    my $self = shift;
    my($op, $cx) = @_;
    my $gv = $self->gv_or_padgv($op);
    return $self->gv_name($gv);
}

sub pp_aelemfast_lex {
    my $self = shift;
    my($op, $cx) = @_;
    my $name = $self->padname($op->targ);
    $name =~ s/^@/\$/;
    my $i = $op->private;
    $i -= 256 if $i > 127;
    return $name . "[" .  ($i + $self->{'arybase'}) . "]";
}

sub pp_aelemfast {
    my $self = shift;
    my($op, $cx) = @_;
    # optimised PADAV, pre 5.15
    return $self->pp_aelemfast_lex(@_) if ($op->flags & OPf_SPECIAL);

    my $gv = $self->gv_or_padgv($op);
    my($name,$quoted) = $self->stash_variable_name('@',$gv);
    $name = $quoted ? "$name->" : '$' . $name;
    my $i = $op->private;
    $i -= 256 if $i > 127;
    return $name . "[" .  ($i + $self->{'arybase'}) . "]";
}

sub rv2x {
    my $self = shift;
    my($op, $cx, $type) = @_;

    if (class($op) eq 'NULL' || !$op->can("first")) {
	carp("Unexpected op in pp_rv2x");
	return 'XXX';
    }
    my $kid = $op->first;
    if ($kid->name eq "gv") {
	return $self->stash_variable($type, $self->deparse($kid, 0), $cx);
    } elsif (is_scalar $kid) {
	my $str = $self->deparse($kid, 0);
	if ($str =~ /^\$([^\w\d])\z/) {
	    # "$$+" isn't a legal way to write the scalar dereference
	    # of $+, since the lexer can't tell you aren't trying to
	    # do something like "$$ + 1" to get one more than your
	    # PID. Either "${$+}" or "$${+}" are workable
	    # disambiguations, but if the programmer did the former,
	    # they'd be in the "else" clause below rather than here.
	    # It's not clear if this should somehow be unified with
	    # the code in dq and re_dq that also adds lexer
	    # disambiguation braces.
	    $str = '$' . "{$1}"; #'
	}
	return $type . $str;
    } else {
	return $type . "{" . $self->deparse($kid, 0) . "}";
    }
}

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 {
    my ($self, $op, $cx) = @_;
    if (!null($op->first) && $op->first->name eq 'null' &&
	$op->first->targ == OP_LIST)
    {
	return $self->rv2x($op->first->first->sibling, $cx, "&")
    }
    else {
	return $self->rv2x($op, $cx, "")
    }
}

sub list_const {
    my $self = shift;
    my($cx, @list) = @_;
    my @a = map $self->const($_, 6), @list;
    if (@a == 0) {
	return "()";
    } elsif (@a == 1) {
	return $a[0];
    } elsif ( @a > 2 and !grep(!/^-?\d+$/, @a)) {
	# collapse (-1,0,1,2) into (-1..2)
	my ($s, $e) = @a[0,-1];
	my $i = $s;
	return $self->maybe_parens("$s..$e", $cx, 9)
	  unless grep $i++ != $_, @a;
    }
    return $self->maybe_parens(join(", ", @a), $cx, 6);
}

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 $self->list_const($cx, $av->ARRAY);
    } else {
	return $self->maybe_local($op, $cx, $self->rv2x($op, $cx, "\@"));
    }
 }

sub is_subscriptable {
    my $op = shift;
    if ($op->name =~ /^([ahg]elem|multideref$)/) {
	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" || $kid->name eq "padcv";
	return 0 if is_scalar($kid);
	return is_subscriptable($kid);	
    } else {
	return 0;
    }
}

sub elem_or_slice_array_name
{
    my $self = shift;
    my ($array, $left, $padname, $allow_arrow) = @_;

    if ($array->name eq $padname) {
	return $self->padany($array);
    } elsif (is_scope($array)) { # ${expr}[0]
	return "{" . $self->deparse($array, 0) . "}";
    } elsif ($array->name eq "gv") {
	($array, my $quoted) =
	    $self->stash_variable_name(
		$left eq '[' ? '@' : '%', $self->gv_or_padgv($array)
	    );
	if (!$allow_arrow && $quoted) {
	    # This cannot happen.
	    die "Invalid variable name $array for slice";
	}
	return $quoted ? "$array->" : $array;
    } elsif (!$allow_arrow || is_scalar $array) { # $x[0], $$x[0], ...
	return $self->deparse($array, 24);
    } else {
	return undef;
    }
}

sub elem_or_slice_single_index
{
    my $self = shift;
    my ($idx) = @_;

    $idx = $self->deparse($idx, 1);

    # Outer parens in an array index will confuse perl
    # if we're interpolating in a regular expression, i.e.
    # /$x$foo[(-1)]/ is *not* the same as /$x$foo[-1]/
    #
    # If $self->{parens}, then an initial '(' will
    # definitely be paired with a final ')'. If
    # !$self->{parens}, the misleading parens won't
    # have been added in the first place.
    #
    # [You might think that we could get "(...)...(...)"
    # where the initial and final parens do not match
    # each other. But we can't, because the above would
    # only happen if there's an infix binop between the
    # two pairs of parens, and *that* means that the whole
    # expression would be parenthesized as well.]
    #
    $idx =~ s/^\((.*)\)$/$1/ if $self->{'parens'};

    # Hash-element braces will autoquote a bareword inside themselves.
    # We need to make sure that C<$hash{warn()}> doesn't come out as
    # C<$hash{warn}>, which has a quite different meaning. Currently
    # B::Deparse will always quote strings, even if the string was a
    # bareword in the original (i.e. the OPpCONST_BARE flag is ignored
    # for constant strings.) So we can cheat slightly here - if we see
    # a bareword, we know that it is supposed to be a function call.
    #
    $idx =~ s/^([A-Za-z_]\w*)$/$1()/;

    return $idx;
}

sub elem {
    my $self = shift;
    my ($op, $cx, $left, $right, $padname) = @_;
    my($array, $idx) = ($op->first, $op->first->sibling);

    $idx = $self->elem_or_slice_single_index($idx);

    unless ($array->name eq $padname) { # Maybe this has been fixed	
	$array = $array->first; # skip rv2av (or ex-rv2av in _53+)
    }
    if (my $array_name=$self->elem_or_slice_array_name
	    ($array, $left, $padname, 1)) {
	return ($array_name =~ /->\z/
		    ? $array_name
		    : $array_name eq '#' ? '${#}' : "\$" . $array_name)
	      . $left . $idx . $right;
    } else {
	# $x[20][3]{hi} or expr->[20]
	my $arrow = is_subscriptable($array) ? "" : "->";
	return $self->deparse($array, 24) . $arrow . $left . $idx . $right;
    }

}

# a simplified version of elem_or_slice_array_name()
# for the use of pp_multideref

sub multideref_var_name {
    my $self = shift;
    my ($gv, $is_hash) = @_;

    my ($name, $quoted) =
        $self->stash_variable_name( $is_hash  ? '%' : '@', $gv);
    return $quoted ? "$name->"
                   : $name eq '#'
                        ? '${#}'       # avoid ${#}[1] => $#[1]
                        : '$' . $name;
}


sub pp_multideref {
    my $self = shift;
    my($op, $cx) = @_;
    my $text = "";

    if ($op->private & OPpMULTIDEREF_EXISTS) {
        $text = $self->keyword("exists"). " ";
    }
    elsif ($op->private & OPpMULTIDEREF_DELETE) {
        $text = $self->keyword("delete"). " ";
    }
    elsif ($op->private & OPpLVAL_INTRO) {
        $text = $self->keyword("local"). " ";
    }

    if ($op->first && ($op->first->flags & OPf_KIDS)) {
        # arbitrary initial expression, e.g. f(1,2,3)->[...]
        my $expr = $self->deparse($op->first, 24);
        # stop "exists (expr)->{...}" being interpreted as
        #"(exists (expr))->{...}"
        $expr = "+$expr" if $expr =~ /^\(/;
        $text .=  $expr;
    }

    my @items = $op->aux_list($self->{curcv});
    my $actions = shift @items;

    my $is_hash;
    my $derefs = 0;

    while (1) {
        if (($actions & MDEREF_ACTION_MASK) == MDEREF_reload) {
            $actions = shift @items;
            next;
        }

        $is_hash = (
           ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_pop_rv2hv_helem
        || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvsv_vivify_rv2hv_helem
        || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padsv_vivify_rv2hv_helem
        || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_vivify_rv2hv_helem
        || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem
        || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem
        );

        if (   ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_padav_aelem
            || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_padhv_helem)
        {
            $derefs = 1;
            $text .= '$' . substr($self->padname(shift @items), 1);
        }
        elsif (   ($actions & MDEREF_ACTION_MASK) == MDEREF_AV_gvav_aelem
               || ($actions & MDEREF_ACTION_MASK) == MDEREF_HV_gvhv_helem)
        {
            $derefs = 1;
            $text .= $self->multideref_var_name(shift @items, $is_hash);
        }
        else {
            if (   ($actions & MDEREF_ACTION_MASK) ==
                                        MDEREF_AV_padsv_vivify_rv2av_aelem
                || ($actions & MDEREF_ACTION_MASK) ==
                                        MDEREF_HV_padsv_vivify_rv2hv_helem)
            {
                $text .= $self->padname(shift @items);
            }
            elsif (   ($actions & MDEREF_ACTION_MASK) ==
                                           MDEREF_AV_gvsv_vivify_rv2av_aelem
                   || ($actions & MDEREF_ACTION_MASK) ==
                                           MDEREF_HV_gvsv_vivify_rv2hv_helem)
            {
                $text .= $self->multideref_var_name(shift @items, $is_hash);
            }
            elsif (   ($actions & MDEREF_ACTION_MASK) ==
                                           MDEREF_AV_pop_rv2av_aelem
                   || ($actions & MDEREF_ACTION_MASK) ==
                                           MDEREF_HV_pop_rv2hv_helem)
            {
                if (   ($op->flags & OPf_KIDS)
                    && (   _op_is_or_was($op->first, OP_RV2AV)
                        || _op_is_or_was($op->first, OP_RV2HV))
                    && ($op->first->flags & OPf_KIDS)
                    && (   _op_is_or_was($op->first->first, OP_AELEM)
                        || _op_is_or_was($op->first->first, OP_HELEM))
                    )
                {
                    $derefs++;
                }
            }

            $text .= '->' if !$derefs++;
        }


        if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_none) {
            last;
        }

        $text .= $is_hash ? '{' : '[';

        if (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_const) {
            my $key = shift @items;
            if ($is_hash) {
                $text .= $self->const($key, $cx);
            }
            else {
                $text .= $key;
            }
        }
        elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_padsv) {
            $text .= $self->padname(shift @items);
        }
        elsif (($actions & MDEREF_INDEX_MASK) == MDEREF_INDEX_gvsv) {
            $text .= '$' .  ($self->stash_variable_name('$', shift @items))[0];
        }

        $text .= $is_hash ? '}' : ']';

        if ($actions & MDEREF_FLAG_last) {
            last;
        }
        $actions >>= MDEREF_SHIFT;
    }

    return $text;
}


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";
    $array = $self->elem_or_slice_array_name($array,$left,$padname,0);
    $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->elem_or_slice_single_index($kid);
    }
    my $lead = '@';
    $lead = '%' if $op->name =~ /^kv/i;
    return $lead . $array . $left . $list . $right;
}

sub pp_aslice   { maybe_local(@_, slice(@_, "[", "]", "rv2av", "padav")) }
sub pp_kvaslice {                 slice(@_, "[", "]", "rv2av", "padav")  }
sub pp_hslice   { maybe_local(@_, slice(@_, "{", "}", "rv2hv", "padhv")) }
sub pp_kvhslice {                 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, $kid;
	}
    } else {
	$obj = $kid;
	$kid = $kid->sibling;
	for (; !null ($kid->sibling) && $kid->name!~/^method(?:_named)?\z/;
	      $kid = $kid->sibling) {
	    push @exprs, $kid
	}
	$meth = $kid;
    }

    if ($meth->name eq "method_named") {
	$meth = $self->meth_sv($meth)->PV;
    } elsif ($meth->name eq "method_super") {
	$meth = "SUPER::".$self->meth_sv($meth)->PV;
    } elsif ($meth->name eq "method_redir") {
        $meth = $self->meth_rclass_sv($meth)->PV.'::'.$self->meth_sv($meth)->PV;
    } elsif ($meth->name eq "method_redir_super") {
        $meth = $self->meth_rclass_sv($meth)->PV.'::SUPER::'.
                $self->meth_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
	}
    }

    return { method => $meth, variable_method => ref($meth),
             object => $obj, args => \@exprs  },
	   $cx;
}

# compat function only
sub method {
    my $self = shift;
    my $info = $self->_method(@_);
    return $self->e_method( $self->_method(@_) );
}

sub e_method {
    my ($self, $info, $cx) = @_;
    my $obj = $self->deparse($info->{object}, 24);

    my $meth = $info->{method};
    $meth = $self->deparse($meth, 1) if $info->{variable_method};
    my $args = join(", ", map { $self->deparse($_, 6) } @{$info->{args}} );
    if ($info->{object}->name eq 'scope' && want_list $info->{object}) {
	# method { $object }
	# This must be deparsed this way to preserve list context
	# of $object.
	my $need_paren = $cx >= 6;
	return '(' x $need_paren
	     . $meth . substr($obj,2) # chop off the "do"
	     . " $args"
	     . ')' x $need_paren;
    }
    my $kid = $obj . "->" . $meth;
    if (length $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;
    return "&" if $self->{'noproto'};
    my($proto, @args) = @_;
    my($arg, $real);
    my $doneok = 0;
    my @reals;
    # An unbackslashed @ or % gobbles up the rest of the args
    1 while $proto =~ s/(?<!\\)([@%])[^\]]+$/$1/;
    $proto =~ s/^\s*//;
    while ($proto) {
	$proto =~ s/^(\\?[\$\@&%*_]|\\\[[\$\@&%*]+\]|;|)\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 "\$" || $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 =~ tr/\\[]//d;
		if ($arg->name =~ /^s?refgen$/ and
		    !null($real = $arg->first) and
		    ($chr =~ /\$/ && is_scalar($real->first)
		     or ($chr =~ /@/
			 && class($real->first->sibling) ne 'NULL'
			 && $real->first->sibling->name
			 =~ /^(rv2|pad)av$/)
		     or ($chr =~ /%/
			 && class($real->first->sibling) ne 'NULL'
			 && $real->first->sibling->name
			 =~ /^(rv2|pad)hv$/)
		     #or ($chr =~ /&/ # This doesn't work
		     #   && $real->first->name eq "rv2cv")
		     or ($chr =~ /\*/
			 && $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 retscalar {
    my $name = $_[0]->name;
    # XXX There has to be a better way of doing this scalar-op check.
    #     Currently PL_opargs is not exposed.
    if ($name eq 'null') {
        $name = substr B::ppname($_[0]->targ), 3
    }
    $name =~ /^(?:scalar|pushmark|wantarray|const|gvsv|gv|padsv|rv2gv
                 |rv2sv|av2arylen|anoncode|prototype|srefgen|ref|bless
                 |regcmaybe|regcreset|regcomp|qr|subst|substcont|trans
                 |transr|sassign|chop|schop|chomp|schomp|defined|undef
                 |study|pos|preinc|i_preinc|predec|i_predec|postinc
                 |i_postinc|postdec|i_postdec|pow|multiply|i_multiply
                 |divide|i_divide|modulo|i_modulo|add|i_add|subtract
                 |i_subtract|concat|stringify|left_shift|right_shift|lt
                 |i_lt|gt|i_gt|le|i_le|ge|i_ge|eq|i_eq|ne|i_ne|ncmp|i_ncmp
                 |slt|sgt|sle|sge|seq|sne|scmp|[sn]?bit_(?:and|x?or)|negate
                 |i_negate|not|[sn]?complement|smartmatch|atan2|sin|cos
                 |rand|srand|exp|log|sqrt|int|hex|oct|abs|length|substr
                 |vec|index|rindex|sprintf|formline|ord|chr|crypt|ucfirst
                 |lcfirst|uc|lc|quotemeta|aelemfast|aelem|exists|helem
                 |pack|join|anonlist|anonhash|push|pop|shift|unshift|xor
                 |andassign|orassign|dorassign|warn|die|reset|nextstate
                 |dbstate|unstack|last|next|redo|dump|goto|exit|open|close
                 |pipe_op|fileno|umask|binmode|tie|untie|tied|dbmopen
                 |dbmclose|select|getc|read|enterwrite|prtf|print|say
                 |sysopen|sysseek|sysread|syswrite|eof|tell|seek|truncate
                 |fcntl|ioctl|flock|send|recv|socket|sockpair|bind|connect
                 |listen|accept|shutdown|gsockopt|ssockopt|getsockname
                 |getpeername|ftrread|ftrwrite|ftrexec|fteread|ftewrite
                 |fteexec|ftis|ftsize|ftmtime|ftatime|ftctime|ftrowned
                 |fteowned|ftzero|ftsock|ftchr|ftblk|ftfile|ftdir|ftpipe
                 |ftsuid|ftsgid|ftsvtx|ftlink|fttty|fttext|ftbinary|chdir
                 |chown|chroot|unlink|chmod|utime|rename|link|symlink
                 |readlink|mkdir|rmdir|open_dir|telldir|seekdir|rewinddir
                 |closedir|fork|wait|waitpid|system|exec|kill|getppid
                 |getpgrp|setpgrp|getpriority|setpriority|time|alarm|sleep
                 |shmget|shmctl|shmread|shmwrite|msgget|msgctl|msgsnd
                 |msgrcv|semop|semget|semctl|hintseval|shostent|snetent
                 |sprotoent|sservent|ehostent|enetent|eprotoent|eservent
                 |spwent|epwent|sgrent|egrent|getlogin|syscall|lock|runcv
                 |fc)\z/x
}

sub pp_entersub {
    my $self = shift;
    my($op, $cx) = @_;
    return $self->e_method($self->_method($op, $cx))
        unless null $op->first->sibling;
    my $prefix = "";
    my $amper = "";
    my($kid, @exprs);
    if ($op->flags & OPf_SPECIAL && !($op->flags & OPf_MOD)) {
	$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;
    my $lexical;
    if (is_scope($kid)) {
	$amper = "&";
	$kid = "{" . $self->deparse($kid, 0) . "}";
    } elsif ($kid->first->name eq "gv") {
	my $gv = $self->gv_or_padgv($kid->first);
	my $cv;
	if (class($gv) eq 'GV' && class($cv = $gv->CV) ne "SPECIAL"
	 || $gv->FLAGS & SVf_ROK && class($cv = $gv->RV) eq 'CV') {
	    $proto = $cv->PV if $cv->FLAGS & SVf_POK;
	}
	$simple = 1; # only calls of named functions can be prototyped
	$kid = $self->deparse($kid, 24);
	my $fq;
	# Fully qualify any sub name that conflicts with a lexical.
	if ($self->lex_in_scope("&$kid")
	 || $self->lex_in_scope("&$kid", 1))
	{
	    $fq++;
	} elsif (!$amper) {
	    if ($kid eq 'main::') {
		$kid = '::';
	    }
	    else {
	      if ($kid !~ /::/ && $kid ne 'x') {
		# Fully qualify any sub name that is also a keyword.  While
		# we could check the import flag, we cannot guarantee that
		# the code deparsed so far would set that flag, so we qual-
		# ify the names regardless of importation.
		if (exists $feature_keywords{$kid}) {
		    $fq++ if $self->feature_enabled($kid);
		} elsif (do { local $@; local $SIG{__DIE__};
			      eval { () = prototype "CORE::$kid"; 1 } }) {
		    $fq++
		}
	      }
	      if ($kid !~ /^(?:\w|::)(?:[\w\d]|::(?!\z))*\z/) {
		$kid = single_delim("q", "'", $kid, $self) . '->';
	      }
	    }
	}
	$fq and substr $kid, 0, 0, = $self->{'curstash'}.'::';
    } elsif (is_scalar ($kid->first) && $kid->first->name ne 'rv2cv') {
	$amper = "&";
	$kid = $self->deparse($kid, 24);
    } else {
	$prefix = "";
	my $grandkid = $kid->first;
	my $arrow = ($lexical = $grandkid->name eq "padcv")
		 || is_subscriptable($grandkid)
		    ? ""
		    : "->";
	$kid = $self->deparse($kid, 24) . $arrow;
	if ($lexical) {
	    my $padlist = $self->{'curcv'}->PADLIST;
	    my $padoff = $grandkid->targ;
	    my $padname = $padlist->ARRAYelt(0)->ARRAYelt($padoff);
	    my $protocv = $padname->FLAGS & SVpad_STATE
		? $padlist->ARRAYelt(1)->ARRAYelt($padoff)
		: $padname->PROTOCV;
	    if ($protocv->FLAGS & SVf_POK) {
		$proto = $protocv->PV
	    }
	    $simple = 1;
	}
    }

    # Doesn't matter how many prototypes there are, if
    # they haven't happened yet!
    my $declared = $lexical || exists $self->{'subs_declared'}{$kid};
    if (not $declared and $self->{'in_coderef2text'}) {
	no strict 'refs';
	no warnings 'uninitialized';
	$declared =
	       (
		 defined &{ ${$self->{'curstash'}."::"}{$kid} }
		 && !exists
		     $self->{'subs_deparsed'}{$self->{'curstash'}."::".$kid}
		 && defined prototype $self->{'curstash'}."::".$kid
	       );
    }
    if (!$declared && defined($proto)) {
	# Avoid "too early to check prototype" warning
	($amper, $proto) = ('&');
    }

    my $args;
    my $listargs = 1;
    if ($declared and defined $proto and not $amper) {
	($amper, $args) = $self->check_proto($proto, @exprs);
	$listargs = $amper;
    }
    if ($listargs) {
	$args = join(", ", map(
		    ($_->flags & OPf_WANT) == OPf_WANT_SCALAR
		 && !retscalar($_)
			? $self->maybe_parens_unop('scalar', $_, 6)
			: $self->deparse($_, 6),
		    @exprs
		));
    }
    if ($prefix or $amper) {
	if ($kid eq '&') { $kid = "{$kid}" } # &{&} cannot be written as &&
	if ($op->flags & OPf_STACKED) {
	    return $prefix . $amper . $kid . "(" . $args . ")";
	} else {
	    return $prefix . $amper. $kid;
	}
    } else {
	# It's a syntax error to call CORE::GLOBAL::foo with a prefix,
	# so it must have been translated from a keyword call. Translate
	# it back.
	$kid =~ s/^CORE::GLOBAL:://;

	my $dproto = defined($proto) ? $proto : "undefined";
	my $scalar_proto = $dproto =~ /^;*(?:[\$*_+]|\\.|\\\[[^]]\])\z/;
        if (!$declared) {
	    return "$kid(" . $args . ")";
	} elsif ($dproto =~ /^\s*\z/) {
	    return $kid;
	} elsif ($scalar_proto and is_scalar($exprs[0])) {
	    # is_scalar is an excessively conservative test here:
	    # really, we should be comparing to the precedence of the
	    # top operator of $exprs[0] (ala unop()), but that would
	    # take some major code restructuring to do right.
	    return $self->maybe_parens_func($kid, $args, $cx, 16);
	} elsif (not $scalar_proto and defined($proto) || $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/(^|\G|[^\\])((?:\\\\)*)([\$\@]|\\[uUlLQE])/$1$2\\$3/g;
    return $str;
}

{
my $bal;
BEGIN {
    use re "eval";
    # Matches any string which is balanced with respect to {braces}
    $bal = qr(
      (?:
	[^\\{}]
      | \\\\
      | \\[{}]
      | \{(??{$bal})\}
      )*
    )x;
}

# the same, but treat $|, $), $( and $ at the end of the string differently
# and leave comments unmangled for the sake of /x and (?x).
sub re_uninterp {
    my($str) = @_;

    $str =~ s/
	  ( ^|\G                  # $1
          | [^\\]
          )

          (                       # $2
            (?:\\\\)*
          )

          (                       # $3
            ( \(\?\??\{$bal\}\)   # $4  (skip over (?{}) and (??{}) blocks)
            | \#[^\n]*            #     (skip over comments)
            )
          | [\$\@]
            (?!\||\)|\(|$|\s)
          | \\[uUlLQE]
          )

	/defined($4) && length($4) ? "$1$2$4" : "$1$2\\$3"/xeg;

    return $str;
}
}

# character escapes, but not delimiters that might need to be escaped
sub escape_str { # ASCII, UTF8
    my($str) = @_;
    $str =~ s/(.)/ord($1) > 255 ? sprintf("\\x{%x}", ord($1)) : $1/eg;
    $str =~ s/\a/\\a/g;
#    $str =~ s/\cH/\\b/g; # \b means something different in a regex; and \cH
                          # isn't a backspace in EBCDIC
    $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' . $unctrl{$1}/ge;
    $str =~ s/([[:^print:]])/sprintf("\\%03o", ord($1))/age;
    return $str;
}

# For regexes.  Leave whitespace unmangled in case of /x or (?x).
sub escape_re {
    my($str) = @_;
    $str =~ s/(.)/ord($1) > 255 ? sprintf("\\x{%x}", ord($1)) : $1/eg;
    $str =~ s/([[:^print:]])/
	($1 =~ y! \t\n!!) ? $1 : sprintf("\\%03o", ord($1))/age;
    $str =~ s/\n/\n\f/g;
    return $str;
}

# Don't do this for regexen
sub unback {
    my($str) = @_;
    $str =~ s/\\/\\\\/g;
    return $str;
}

# Remove backslashes which precede literal control characters,
# to avoid creating ambiguity when we escape the latter.
sub re_unback {
    my($str) = @_;

    # the insane complexity here is due to the behaviour of "\c\"
    $str =~ s/(^|[^\\]|\\c\\)(?<!\\c)\\(\\\\)*(?=[[:^print:]])/$1$2/g;
    return $str;
}

sub balanced_delim {
    my($str) = @_;
    my @str = split //, $str;
    my($ar, $open, $close, $fail, $c, $cnt, $last_bs);
    for $ar (['[',']'], ['(',')'], ['<','>'], ['{','}']) {
	($open, $close) = @$ar;
	$fail = 0; $cnt = 0; $last_bs = 0;
	for $c (@str) {
	    if ($c eq $open) {
		$fail = 1 if $last_bs;
		$cnt++;
	    } elsif ($c eq $close) {
		$fail = 1 if $last_bs;
		$cnt--;
		if ($cnt < 0) {
		    # qq()() isn't ")("
		    $fail = 1;
		    last;
		}
	    }
	    $last_bs = $c eq '\\';
	}
	$fail = 1 if $cnt != 0;
	return ($open, "$open$str$close") if not $fail;
    }
    return ("", $str);
}

sub single_delim {
    my($q, $default, $str, $self) = @_;
    return "$default$str$default" if $default and index($str, $default) == -1;
    my $coreq = $self->keyword($q); # maybe CORE::q
    if ($q ne 'qr') {
	(my $succeed, $str) = balanced_delim($str);
	return "$coreq$str" if $succeed;
    }
    for my $delim ('/', '"', '#') {
	return "$coreq$delim" . $str . $delim if index($str, $delim) == -1;
    }
    if ($default) {
	$str =~ s/$default/\\$default/g;
	return "$default$str$default";
    } else {
	$str =~ s[/][\\/]g;
	return "$coreq/$str/";
    }
}

my $max_prec;
BEGIN { $max_prec = int(0.999 + 8*length(pack("F", 42))*log(2)/log(10)); }

# Split a floating point number into an integer mantissa and a binary
# exponent. Assumes you've already made sure the number isn't zero or
# some weird infinity or NaN.
sub split_float {
    my($f) = @_;
    my $exponent = 0;
    if ($f == int($f)) {
	while ($f % 2 == 0) {
	    $f /= 2;
	    $exponent++;
	}
    } else {
	while ($f != int($f)) {
	    $f *= 2;
	    $exponent--;
	}
    }
    my $mantissa = sprintf("%.0f", $f);
    return ($mantissa, $exponent);
}

sub const {
    my $self = shift;
    my($sv, $cx) = @_;
    if ($self->{'use_dumper'}) {
	return $self->const_dumper($sv, $cx);
    }
    if (class($sv) eq "SPECIAL") {
	# sv_undef, sv_yes, sv_no
	return $$sv == 3 ? $self->maybe_parens("!1", $cx, 21)
			 : ('undef', '1')[$$sv-1];
    }
    if (class($sv) eq "NULL") {
       return 'undef';
    }
    # convert a version object into the "v1.2.3" string in its V magic
    if ($sv->FLAGS & SVs_RMG) {
	for (my $mg = $sv->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
	    return $mg->PTR if $mg->TYPE eq 'V';
	}
    }

    if ($sv->FLAGS & SVf_IOK) {
	my $str = $sv->int_value;
	$str = $self->maybe_parens($str, $cx, 21) if $str < 0;
	return $str;
    } elsif ($sv->FLAGS & SVf_NOK) {
	my $nv = $sv->NV;
	if ($nv == 0) {
	    if (pack("F", $nv) eq pack("F", 0)) {
		# positive zero
		return "0";
	    } else {
		# negative zero
		return $self->maybe_parens("-.0", $cx, 21);
	    }
	} elsif (1/$nv == 0) {
	    if ($nv > 0) {
		# positive infinity
		return $self->maybe_parens("9**9**9", $cx, 22);
	    } else {
		# negative infinity
		return $self->maybe_parens("-9**9**9", $cx, 21);
	    }
	} elsif ($nv != $nv) {
	    # NaN
	    if (pack("F", $nv) eq pack("F", sin(9**9**9))) {
		# the normal kind
		return "sin(9**9**9)";
	    } elsif (pack("F", $nv) eq pack("F", -sin(9**9**9))) {
		# the inverted kind
		return $self->maybe_parens("-sin(9**9**9)", $cx, 21);
	    } else {
		# some other kind
		my $hex = unpack("h*", pack("F", $nv));
		return qq'unpack("F", pack("h*", "$hex"))';
	    }
	}
	# first, try the default stringification
	my $str = "$nv";
	if ($str != $nv) {
	    # failing that, try using more precision
	    $str = sprintf("%.${max_prec}g", $nv);
#	    if (pack("F", $str) ne pack("F", $nv)) {
	    if ($str != $nv) {
		# not representable in decimal with whatever sprintf()
		# and atof() Perl is using here.
		my($mant, $exp) = split_float($nv);
		return $self->maybe_parens("$mant * 2**$exp", $cx, 19);
	    }
	}
	$str = $self->maybe_parens($str, $cx, 21) if $nv < 0;
	return $str;
    } elsif ($sv->FLAGS & SVf_ROK && $sv->can("RV")) {
	my $ref = $sv->RV;
	my $class = class($ref);
	if ($class eq "AV") {
	    return "[" . $self->list_const(2, $ref->ARRAY) . "]";
	} elsif ($class eq "HV") {
	    my %hash = $ref->ARRAY;
	    my @elts;
	    for my $k (sort keys %hash) {
		push @elts, "$k => " . $self->const($hash{$k}, 6);
	    }
	    return "{" . join(", ", @elts) . "}";
	} elsif ($class eq "CV") {
	    BEGIN {
		if ($] > 5.0150051) {
		    require overloading;
		    unimport overloading;
		}
	    }
	    if ($] > 5.0150051 && $self->{curcv} &&
		 $self->{curcv}->object_2svref == $ref->object_2svref) {
		return $self->keyword("__SUB__");
	    }
	    return "sub " . $self->deparse_sub($ref);
	}
	if ($class ne 'SPECIAL' and $ref->FLAGS & SVs_SMG) {
	    for (my $mg = $ref->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
		if ($mg->TYPE eq 'r') {
		    my $re = re_uninterp(escape_re(re_unback($mg->precomp)));
		    return single_delim("qr", "", $re, $self);
		}
	    }
	}
	
	my $const = $self->const($ref, 20);
	if ($self->{in_subst_repl} && $const =~ /^[0-9]/) {
	    $const = "($const)";
	}
	return $self->maybe_parens("\\$const", $cx, 20);
    } elsif ($sv->FLAGS & SVf_POK) {
	my $str = $sv->PV;
	if ($str =~ /[[:^print:]]/a) {
	    return single_delim("qq", '"',
				 uninterp(escape_str unback $str), $self);
	} else {
	    return single_delim("q", "'", unback($str), $self);
	}
    } else {
	return "undef";
    }
}

sub const_dumper {
    my $self = shift;
    my($sv, $cx) = @_;
    my $ref = $sv->object_2svref();
    my $dumper = Data::Dumper->new([$$ref], ['$v']);
    $dumper->Purity(1)->Terse(1)->Deparse(1)->Indent(0)->Useqq(1)->Sortkeys(1);
    my $str = $dumper->Dump();
    if ($str =~ /^\$v/) {
	return '${my ' . $str . ' \$v}';
    } else {
	return $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 meth_sv {
    my $self = shift;
    my $op = shift;
    my $sv = $op->meth_sv;
    # the constant could be in the pad (under useithreads)
    $sv = $self->padval($op->targ) unless $$sv;
    return $sv;
}

sub meth_rclass_sv {
    my $self = shift;
    my $op = shift;
    my $sv = $op->rclass;
    # the constant could be in the pad (under useithreads)
    $sv = $self->padval($sv) unless ref $sv;
    return $sv;
}

sub pp_const {
    my $self = shift;
    my($op, $cx) = @_;
    if ($op->private & OPpCONST_ARYBASE) {
        return '$[';
    }
#    if ($op->private & OPpCONST_BARE) { # trouble with '=>' autoquoting
#	return $self->const_sv($op)->PV;
#    }
    my $sv = $self->const_sv($op);
    return $self->const($sv, $cx);
}

sub dq {
    my $self = shift;
    my $op = shift;
    my $type = $op->name;
    if ($type eq "const") {
	return '$[' if $op->private & OPpCONST_ARYBASE;
	return uninterp(escape_str(unback($self->const_sv($op)->as_string)));
    } elsif ($type eq "concat") {
	my $first = $self->dq($op->first);
	my $last  = $self->dq($op->last);

	# Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]", "$foo\::bar"
	($last =~ /^[A-Z\\\^\[\]_?]/ &&
	    $first =~ s/([\$@])\^$/${1}{^}/)  # "${^}W" etc
	    || ($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 "fc") {
	return '\F' . $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 if it exists (readpipe() vs ``)
    my $child = $op->first->sibling->isa('B::NULL')
	? $op->first : $op->first->sibling;
    if ($self->pure_string($child)) {
	return single_delim("qx", '`', $self->dq($child, 1), $self);
    }
    unop($self, @_, "readpipe");
}

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]),
					   $self)});
}

# OP_STRINGIFY is a listop, but it only ever has one arg
sub pp_stringify {
    my ($self, $op, $cx) = @_;
    my $kid = $op->first->sibling;
    while ($kid->name eq 'null' && !null($kid->first)) {
	$kid = $kid->first;
    }
    if ($kid->name =~ /^(?:const|padsv|rv2sv|av2arylen|gvsv|multideref
			  |aelemfast(?:_lex)?|[ah]elem|join|concat)\z/x) {
	maybe_targmy(@_, \&dquote);
    }
    else {
	# Actually an optimised join.
	my $result = listop(@_,"join");
	$result =~ s/join([( ])/join$1$self->{'ex_const'}, /;
	$result;
    }
}

# 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/";	
    }
}

# Only used by tr///, so backslashes hyphens
sub pchr { # ASCII
    my($n) = @_;
    if ($n == ord '\\') {
	return '\\\\';
    } elsif ($n == ord "-") {
	return "\\-";
    } elsif (utf8::native_to_unicode($n) >= utf8::native_to_unicode(ord(' '))
             and utf8::native_to_unicode($n) <= utf8::native_to_unicode(ord('~')))
    {
        # I'm presuming a regex is not ok here, otherwise we could have used
        # /[[:print:]]/a to get here
	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' . $unctrl{chr $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;
}

sub tr_decode_byte {
    my($table, $flags) = @_;
    my(@table) = unpack("s*", $table);
    splice @table, 0x100, 1;   # Number of subsequent elements
    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 < @table; $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 "\\-";
    } elsif ($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, $morflags) = @_;
    my($from, $to);
    my $class = class($op);
    my $priv_flags = $op->private;
    if ($class eq "PVOP") {
	($from, $to) = tr_decode_byte($op->pv, $priv_flags);
    } elsif ($class eq "PADOP") {
	($from, $to)
	  = tr_decode_utf8($self->padval($op->padix)->RV, $priv_flags);
    } else { # class($op) eq "SVOP"
	($from, $to) = tr_decode_utf8($op->sv->RV, $priv_flags);
    }
    my $flags = "";
    $flags .= "c" if $priv_flags & OPpTRANS_COMPLEMENT;
    $flags .= "d" if $priv_flags & OPpTRANS_DELETE;
    $to = "" if $from eq $to and $flags eq "";
    $flags .= "s" if $priv_flags & OPpTRANS_SQUASH;
    $flags .= $morflags if defined $morflags;
    my $ret = $self->keyword("tr") . double_delim($from, $to) . $flags;
    if (my $targ = $op->targ) {
	return $self->maybe_parens($self->padname($targ) . " =~ $ret",
				   $cx, 20);
    }
    return $ret;
}

sub pp_transr { push @_, 'r'; goto &pp_trans }

sub re_dq_disambiguate {
    my ($first, $last) = @_;
    # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]"
    ($last =~ /^[A-Z\\\^\[\]_?]/ &&
	$first =~ s/([\$@])\^$/${1}{^}/)  # "${^}W" etc
	|| ($last =~ /^[{\[\w_]/ &&
	    $first =~ s/([\$@])([A-Za-z_]\w*)$/${1}{$2}/);
    return $first . $last;
}

# Like dq(), but different
sub re_dq {
    my $self = shift;
    my ($op) = @_;

    my $type = $op->name;
    if ($type eq "const") {
	return '$[' if $op->private & OPpCONST_ARYBASE;
	my $unbacked = re_unback($self->const_sv($op)->as_string);
	return re_uninterp(escape_re($unbacked));
    } elsif ($type eq "concat") {
	my $first = $self->re_dq($op->first);
	my $last  = $self->re_dq($op->last);
	return re_dq_disambiguate($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 "fc") {
	return '\F' . $self->re_dq($op->first->sibling) . '\E';
    } elsif ($type eq "join") {
	return $self->deparse($op->last, 26); # was join($", @ary)
    } else {
	my $ret = $self->deparse($op, 26);
	$ret =~ s/^\$([(|)])\z/\${$1}/ # $( $| $) need braces
	or $ret =~ s/^\@([-+])\z/\@{$1}/; # @- @+ need braces
	return $ret;
    }
}

sub pure_string {
    my ($self, $op) = @_;
    return 0 if null $op;
    my $type = $op->name;

    if ($type eq 'const' || $type eq 'av2arylen') {
	return 1;
    }
    elsif ($type =~ /^(?:[ul]c(first)?|fc)$/ || $type eq 'quotemeta') {
	return $self->pure_string($op->first->sibling);
    }
    elsif ($type eq 'join') {
	my $join_op = $op->first->sibling;  # Skip pushmark
	return 0 unless $join_op->name eq 'null' && $join_op->targ == OP_RV2SV;

	my $gvop = $join_op->first;
	return 0 unless $gvop->name eq 'gvsv';
        return 0 unless '"' eq $self->gv_name($self->gv_or_padgv($gvop));

	return 0 unless ${$join_op->sibling} eq ${$op->last};
	return 0 unless $op->last->name =~ /^(?:[ah]slice|(?:rv2|pad)av)$/;
    }
    elsif ($type eq 'concat') {
	return $self->pure_string($op->first)
            && $self->pure_string($op->last);
    }
    elsif (is_scalar($op) || $type =~ /^[ah]elem$/) {
	return 1;
    }
    elsif ($type eq "null" and $op->can('first') and not null $op->first) {
        my $first = $op->first;

        return 1 if $first->name eq "multideref";
        return 1 if $first->name eq "aelemfast_lex";

        if (    $first->name eq "null"
            and $first->can('first')
	    and not null $first->first
            and $first->first->name eq "aelemfast"
	   )
        {
            return 1;
        }
    }

    return 0;
}

sub code_list {
    my ($self,$op,$cv) = @_;

    # localise stuff relating to the current sub
    $cv and
	local($self->{'curcv'}) = $cv,
	local($self->{'curcvlex'}),
	local(@$self{qw'curstash warnings hints hinthash curcop'})
	    = @$self{qw'curstash warnings hints hinthash curcop'};

    my $re;
    for ($op = $op->first->sibling; !null($op); $op = $op->sibling) {
	if ($op->name eq 'null' and $op->flags & OPf_SPECIAL) {
	    my $scope = $op->first;
	    # 0 context (last arg to scopeop) means statement context, so
	    # the contents of the block will not be wrapped in do{...}.
	    my $block = scopeop($scope->first->name eq "enter", $self,
				$scope, 0);
	    # next op is the source code of the block
	    $op = $op->sibling;
	    $re .= ($self->const_sv($op)->PV =~ m|^(\(\?\??\{)|)[0];
	    my $multiline = $block =~ /\n/;
	    $re .= $multiline ? "\n\t" : ' ';
	    $re .= $block;
	    $re .= $multiline ? "\n\b})" : " })";
	} else {
	    $re = re_dq_disambiguate($re, $self->re_dq($op));
	}
    }
    $re;
}

sub 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";
    my $kname = $kid->name;
    if ($kname eq "null" and !null($kid->first)
	and $kid->first->name eq 'pushmark')
    {
	my $str = '';
	$kid = $kid->first->sibling;
	while (!null($kid)) {
	    my $first = $str;
	    my $last = $self->re_dq($kid);
	    $str = re_dq_disambiguate($first, $last);
	    $kid = $kid->sibling;
	}
	return $str, 1;
    }

    return ($self->re_dq($kid), 1)
	if $kname =~ /^(?:rv2|pad)av/ or $self->pure_string($kid);
    return ($self->deparse($kid, $cx), 0);
}

sub pp_regcomp {
    my ($self, $op, $cx) = @_;
    return (($self->regcomp($op, $cx, 0))[0]);
}

sub re_flags {
    my ($self, $op) = @_;
    my $flags = '';
    my $pmflags = $op->pmflags;
    if (!$pmflags) {
	my $re = $op->pmregexp;
	if ($$re) {
	    $pmflags = $re->compflags;
	}
    }
    $flags .= "g" if $pmflags & PMf_GLOBAL;
    $flags .= "i" if $pmflags & PMf_FOLD;
    $flags .= "m" if $pmflags & PMf_MULTILINE;
    $flags .= "o" if $pmflags & PMf_KEEP;
    $flags .= "s" if $pmflags & PMf_SINGLELINE;
    $flags .= "x" if $pmflags & PMf_EXTENDED;
    $flags .= "x" if $pmflags & PMf_EXTENDED_MORE;
    $flags .= "p" if $pmflags & PMf_KEEPCOPY;
    $flags .= "n" if $pmflags & PMf_NOCAPTURE;
    if (my $charset = $pmflags & PMf_CHARSET) {
	# Hardcoding this is fragile, but B does not yet export the
	# constants we need.
	$flags .= qw(d l u a aa)[$charset >> 7]
    }
    # The /d flag is indicated by 0; only show it if necessary.
    elsif ($self->{hinthash} and
	     $self->{hinthash}{reflags_charset}
	    || $self->{hinthash}{feature_unicode}
	or $self->{hints} & $feature::hint_mask
	  && ($self->{hints} & $feature::hint_mask)
	       != $feature::hint_mask
	  && $self->{hints} & $feature::hint_uni8bit
    ) {
	$flags .= 'd';
    }
    $flags;
}

# 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', 'soup', 'soupmix');

# When deparsing a regular expression with code blocks, we have to look in
# various places to find the blocks.
#
# For qr/(?{...})/ without interpolation, the CV is under $qr->qr_anoncv
# and the code list (list of blocks and constants, maybe vars) is under
# $cv->ROOT->first->code_list:
#   ./perl -Ilib -MB -e 'use O "Concise", B::svref_2object(sub {qr/(?{die})/})->ROOT->first->first->sibling->pmregexp->qr_anoncv->object_2svref'
#
# For qr/$a(?{...})/ with interpolation, the code list is more accessible,
# under $pmop->code_list, but the $cv is something you have to dig for in
# the regcomp op’s kids:
#   ./perl -Ilib -mO=Concise -e 'qr/$a(?{die})/'
#
# For m// and split //, things are much simpler.  There is no CV.  The code
# list is under $pmop->code_list.

sub matchop {
    my $self = shift;
    my($op, $cx, $name, $delim) = @_;
    my $kid = $op->first;
    my ($binop, $var, $re) = ("", "", "");
    if ($op->name ne 'split' && $op->flags & OPf_STACKED) {
	$binop = 1;
	$var = $self->deparse($kid, 20);
	$kid = $kid->sibling;
    }
           # not $name; $name will be 'm' for both match and split
    elsif ($op->name eq 'match' and my $targ = $op->targ) {
	$binop = 1;
	$var = $self->padname($targ);
    }
    my $quote = 1;
    my $pmflags = $op->pmflags;
    my $rhs_bound_to_defsv;
    my ($cv, $bregexp);
    my $have_kid = !null $kid;
    # Check for code blocks first
    if (not null my $code_list = $op->code_list) {
	$re = $self->code_list($code_list,
			       $op->name eq 'qr'
				   ? $self->padval(
				         $kid->first   # ex-list
					     ->first   #   pushmark
					     ->sibling #   entersub
					     ->first   #     ex-list
					     ->first   #       pushmark
					     ->sibling #       srefgen
					     ->first   #         ex-list
					     ->first   #           anoncode
					     ->targ
				     )
				   : undef);
    } elsif (${$bregexp = $op->pmregexp} && ${$cv = $bregexp->qr_anoncv}) {
	my $patop = $cv->ROOT      # leavesub
		       ->first     #   qr
		       ->code_list;#     list
	$re = $self->code_list($patop, $cv);
    } elsif (!$have_kid) {
	$re = re_uninterp(escape_re(re_unback($op->precomp)));
    } elsif ($kid->name ne 'regcomp') {
        if ($op->name eq 'split') {
            # split has other kids, not just regcomp
            $re = re_uninterp(escape_re(re_unback($op->precomp)));
        }
        else {
            carp("found ".$kid->name." where regcomp expected");
        }
    } else {
	($re, $quote) = $self->regcomp($kid, 21);
    }
    if ($have_kid and $kid->name eq 'regcomp') {
	my $matchop = $kid->first;
	if ($matchop->name eq 'regcreset') {
	    $matchop = $matchop->first;
	}
	if ($matchop->name =~ /^(?:match|transr?|subst)\z/
	   && $matchop->flags & OPf_SPECIAL) {
	    $rhs_bound_to_defsv = 1;
	}
    }
    my $flags = "";
    $flags .= "c" if $pmflags & PMf_CONTINUE;
    $flags .= $self->re_flags($op);
    $flags = join '', sort split //, $flags;
    $flags = $matchwords{$flags} if $matchwords{$flags};
    if ($pmflags & PMf_ONCE) { # only one kind of delimiter works here
	$re =~ s/\?/\\?/g;
	$re = $self->keyword("m") . "?$re?";     # explicit 'm' is required
    } elsif ($quote) {
	$re = single_delim($name, $delim, $re, $self);
    }
    $re = $re . $flags if $quote;
    if ($binop) {
	return
	 $self->maybe_parens(
	  $rhs_bound_to_defsv
	   ? "$var =~ (\$_ =~ $re)"
	   : "$var =~ $re",
	  $cx, 20
	 );
    } else {
	return $re;
    }
}

sub pp_match { matchop(@_, "m", "/") }
sub pp_qr { matchop(@_, "qr", "") }

sub pp_runcv { unop(@_, "__SUB__"); }

sub pp_split {
    my $self = shift;
    my($op, $cx) = @_;
    my($kid, @exprs, $ary, $expr);
    my $stacked = $op->flags & OPf_STACKED;

    $kid = $op->first;
    $kid = $kid->sibling if $kid->name eq 'regcomp';
    for (; !null($kid); $kid = $kid->sibling) {
	push @exprs, $self->deparse($kid, 6);
    }

    unshift @exprs, $self->matchop($op, $cx, "m", "/");

    if ($op->private & OPpSPLIT_ASSIGN) {
        # With C<@array = split(/pat/, str);>,
        #  array is stored in split's pmreplroot; either
        # as an integer index into the pad (for a lexical array)
        # or as GV for a package array (which will be a pad index
        # on threaded builds)
        # With my/our @array = split(/pat/, str), the array is instead
        # accessed via an extra padav/rv2av op at the end of the
        # split's kid ops.

        if ($stacked) {
            $ary = pop @exprs;
        }
        else {
            if ($op->private & OPpSPLIT_LEX) {
                $ary = $self->padname($op->pmreplroot);
            }
            else {
                # union with op_pmtargetoff, op_pmtargetgv
                my $gv = $op->pmreplroot;
                $gv = $self->padval($gv) if !ref($gv);
                $ary = $self->maybe_local(@_,
			      $self->stash_variable('@',
						     $self->gv_name($gv),
						     $cx))
            }
            if ($op->private & OPpLVAL_INTRO) {
                $ary = $op->private & OPpSPLIT_LEX ? "my $ary" : "local $ary";
            }
        }
    }

    # handle special case of split(), and split(' ') that compiles to /\s+/
    $exprs[0] = q{' '} if ($op->reflags // 0) & RXf_SKIPWHITE();

    $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', 'rogue',
    'sir', 'rise', 'smore', 'more', 'seer', 'rome', 'gore', 'grim', 'grime',
    'or', 'rose', 'rosie');

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;
    }
    elsif (my $targ = $op->targ) {
	$binop = 1;
	$var = $self->padname($targ);
    }
    my $flags = "";
    my $pmflags = $op->pmflags;
    if (null($op->pmreplroot)) {
	$repl = $kid;
	$kid = $kid->sibling;
    } else {
	$repl = $op->pmreplroot->first; # skip substcont
    }
    while ($repl->name eq "entereval") {
	    $repl = $repl->first;
	    $flags .= "e";
    }
    {
	local $self->{in_subst_repl} = 1;
	if ($pmflags & PMf_EVAL) {
	    $repl = $self->deparse($repl->first, 0);
	} else {
	    $repl = $self->dq($repl);	
	}
    }
    if (not null my $code_list = $op->code_list) {
	$re = $self->code_list($code_list);
    } elsif (null $kid) {
	$re = re_uninterp(escape_re(re_unback($op->precomp)));
    } else {
	($re) = $self->regcomp($kid, 1);
    }
    $flags .= "r" if $pmflags & PMf_NONDESTRUCT;
    $flags .= "e" if $pmflags & PMf_EVAL;
    $flags .= $self->re_flags($op);
    $flags = join '', sort split //, $flags;
    $flags = $substwords{$flags} if $substwords{$flags};
    my $core_s = $self->keyword("s"); # maybe CORE::s
    if ($binop) {
	return $self->maybe_parens("$var =~ $core_s"
				   . double_delim($re, $repl) . $flags,
				   $cx, 20);
    } else {
	return "$core_s". double_delim($re, $repl) . $flags;	
    }
}

sub is_lexical_subs {
    my (@ops) = shift;
    for my $op (@ops) {
        return 0 if $op->name !~ /\A(?:introcv|clonecv)\z/;
    }
    return 1;
}

# Pretend these two ops do not exist.  The perl parser adds them to the
# beginning of any block containing my-sub declarations, whereas we handle
# the subs in pad_subs and next_todo.
*pp_clonecv = *pp_introcv;
sub pp_introcv {
    my $self = shift;
    my($op, $cx) = @_;
    # For now, deparsing doesn't worry about the distinction between introcv
    # and clonecv, so pretend this op doesn't exist:
    return '';
}

sub pp_padcv {
    my $self = shift;
    my($op, $cx) = @_;
    return $self->padany($op);
}

my %lvref_funnies = (
    OPpLVREF_SV, => '$',
    OPpLVREF_AV, => '@',
    OPpLVREF_HV, => '%',
    OPpLVREF_CV, => '&',
);

sub pp_refassign {
    my ($self, $op, $cx) = @_;
    my $left;
    if ($op->private & OPpLVREF_ELEM) {
	$left = $op->first->sibling;
	$left = maybe_local(@_, elem($self, $left, undef,
				     $left->targ == OP_AELEM
					? qw([ ] padav)
					: qw({ } padhv)));
    } elsif ($op->flags & OPf_STACKED) {
	$left = maybe_local(@_,
			    $lvref_funnies{$op->private & OPpLVREF_TYPE}
			  . $self->deparse($op->first->sibling));
    } else {
	$left = &pp_padsv;
    }
    my $right = $self->deparse_binop_right($op, $op->first, 7);
    return $self->maybe_parens("\\$left = $right", $cx, 7);
}

sub pp_lvref {
    my ($self, $op, $cx) = @_;
    my $code;
    if ($op->private & OPpLVREF_ELEM) {
	$code = $op->first->name =~ /av\z/ ? &pp_aelem : &pp_helem;
    } elsif ($op->flags & OPf_STACKED) {
	$code = maybe_local(@_,
			    $lvref_funnies{$op->private & OPpLVREF_TYPE}
			  . $self->deparse($op->first));
    } else {
	$code = &pp_padsv;
    }
    "\\$code";
}

sub pp_lvrefslice {
    my ($self, $op, $cx) = @_;
    '\\' . ($op->last->name =~ /av\z/ ? &pp_aslice : &pp_hslice);
}

sub pp_lvavref {
    my ($self, $op, $cx) = @_;
    '\\(' . ($op->flags & OPf_STACKED
		? maybe_local(@_, rv2x(@_, "\@"))
		: &pp_padsv)  . ')'
}


sub pp_argcheck {
    my $self = shift;
    my($op, $cx) = @_;
    my ($params, $opt_params, $slurpy) = $op->aux_list($self->{curcv});
    my $mandatory = $params - $opt_params;
    my $check = '';

    $check .= <<EOF if !$slurpy;
die sprintf("Too many arguments for subroutine at %s line %d.\\n", (caller)[1, 2]) unless \@_ <= $params;
EOF

    $check .= <<EOF if $mandatory > 0;
die sprintf("Too few arguments for subroutine at %s line %d.\\n", (caller)[1, 2]) unless \@_ >= $mandatory;
EOF

    my $cond = ($params & 1) ? 'unless' : 'if';
    $check .= <<EOF if $slurpy eq '%';
die sprintf("Odd name/value argument for subroutine at %s line %d.\\n", (caller)[1, 2]) if \@_ > $params && ((\@_ - $params) & 1);
EOF

    $check =~ s/;\n\z//;
    return $check;
}


sub pp_argelem {
    my $self = shift;
    my($op, $cx) = @_;
    my $var = $self->padname($op->targ);
    my $ix  = $op->string($self->{curcv});
    my $expr;
    if ($op->flags & OPf_KIDS) {
        $expr = $self->deparse($op->first, 7);
    }
    elsif ($var =~ /^[@%]/) {
        $expr = $ix ? "\@_[$ix .. \$#_]" : '@_';
    }
    else {
        $expr = "\$_[$ix]";
    }
    return "my $var = $expr";
}


sub pp_argdefelem {
    my $self = shift;
    my($op, $cx) = @_;
    my $ix  = $op->targ;
    my $expr = "\@_ >= " . ($ix+1) . " ? \$_[$ix] : ";
    my $def = $self->deparse($op->first, 7);
    $def = "($def)" if $op->first->flags & OPf_PARENS;
    $expr .= $self->deparse($op->first, $cx);
    return $expr;
}


1;
__END__

=head1 NAME

B::Deparse - Perl compiler backend to produce perl code

=head1 SYNOPSIS

B<perl> B<-MO=Deparse>[B<,-d>][B<,-f>I<FILE>][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.

While B::Deparse goes to some lengths to try to figure out what your
original program was doing, some parts of the language can still trip
it up; it still fails even on some parts of Perl's own test suite.  If
you encounter a failure other than the most common ones described in
the BUGS section below, you can help contribute to B::Deparse's
ongoing development by submitting a bug report with a small
example.

=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<-d>

Output data values (when they appear as constants) using Data::Dumper.
Without this option, B::Deparse will use some simple routines of its
own for the same purpose.  Currently, Data::Dumper is better for some
kinds of data (such as complex structures with sharing and
self-reference) while the built-in routines are better for others
(such as odd floating-point values).

=item B<-f>I<FILE>

Normally, B::Deparse deparses the main code of a program, and all the subs
defined in the same file.  To include subs defined in
other files, pass the B<-f> option with the filename.
You can pass the B<-f> option several times, to
include more than one secondary file.  (Most of the time you don't want to
use it at all.)  You can also use this option to include subs which are
defined in the scope of a B<#line> directive with two parameters.

=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<-P>

Disable prototype checking.  With this option, all function calls are
deparsed as if no prototype was defined for them.  In other words,

    perl -MO=Deparse,-P -e 'sub foo (\@) { 1 } foo @x'

will print

    sub foo (\@) {
	1;
    }
    &foo(\@x);

making clear how the parameters are actually passed to C<foo>.

=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<-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, C<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 5, C<use> declarations will be translated into
C<BEGIN> blocks containing calls to C<require> and C<import>; for
instance,

    use strict 'refs';

turns into

    sub BEGIN {
        require strict;
        do {
            'strict'->import('refs')
        };
    }

If I<LEVEL> is at least 7, C<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.

=head2 ambient_pragmas

    $deparse->ambient_pragmas(strict => 'all', '$[' => $[);

The compilation of a subroutine can be affected by a few compiler
directives, B<pragmas>.  These are:

=over 4

=item *

use strict;

=item *

use warnings;

=item *

Assigning to the special variable $[

=item *

use integer;

=item *

use bytes;

=item *

use utf8;

=item *

use re;

=back

Ordinarily, if you use B::Deparse on a subroutine which has
been compiled in the presence of one or more of these pragmas,
the output will include statements to turn on the appropriate
directives.  So if you then compile the code returned by coderef2text,
it will behave the same way as the subroutine which you deparsed.

However, you may know that you intend to use the results in a
particular context, where some pragmas are already in scope.  In
this case, you use the B<ambient_pragmas> method to describe the
assumptions you wish to make.

Not all of the options currently have any useful effect.  See
L</BUGS> for more details.

The parameters it accepts are:

=over 4

=item strict

Takes a string, possibly containing several values separated
by whitespace.  The special values "all" and "none" mean what you'd
expect.

    $deparse->ambient_pragmas(strict => 'subs refs');

=item $[

Takes a number, the value of the array base $[.
Cannot be non-zero on Perl 5.15.3 or later.

=item bytes

=item utf8

=item integer

If the value is true, then the appropriate pragma is assumed to
be in the ambient scope, otherwise not.

=item re

Takes a string, possibly containing a whitespace-separated list of
values.  The values "all" and "none" are special.  It's also permissible
to pass an array reference here.

    $deparser->ambient_pragmas(re => 'eval');


=item warnings

Takes a string, possibly containing a whitespace-separated list of
values.  The values "all" and "none" are special, again.  It's also
permissible to pass an array reference here.

    $deparser->ambient_pragmas(warnings => [qw[void io]]);

If one of the values is the string "FATAL", then all the warnings
in that list will be considered fatal, just as with the B<warnings>
pragma itself.  Should you need to specify that some warnings are
fatal, and others are merely enabled, you can pass the B<warnings>
parameter twice:

    $deparser->ambient_pragmas(
	warnings => 'all',
	warnings => [FATAL => qw/void io/],
    );

See L<warnings> for more information about lexical warnings.

=item hint_bits

=item warning_bits

These two parameters are used to specify the ambient pragmas in
the format used by the special variables $^H and ${^WARNING_BITS}.

They exist principally so that you can write code like:

    { my ($hint_bits, $warning_bits);
    BEGIN {($hint_bits, $warning_bits) = ($^H, ${^WARNING_BITS})}
    $deparser->ambient_pragmas (
	hint_bits    => $hint_bits,
	warning_bits => $warning_bits,
	'$['         => 0 + $[
    ); }

which specifies that the ambient pragmas are exactly those which
are in scope at the point of calling.

=item %^H

This parameter is used to specify the ambient pragmas which are
stored in the special hash %^H.

=back

=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

=over 4

=item *

In Perl 5.20 and earlier, the only pragmas to
be completely supported are: C<use warnings>,
C<use strict>, C<use bytes>, C<use integer>
and C<use feature>.  (C<$[>, which
behaves like a pragma, is also supported.)

Excepting those listed above, we're currently unable to guarantee that
B::Deparse will produce a pragma at the correct point in the program.
(Specifically, pragmas at the beginning of a block often appear right
before the start of the block instead.)
Since the effects of pragmas are often lexically scoped, this can mean
that the pragma holds sway over a different portion of the program
than in the input file.

=item *

In fact, the above is a specific instance of a more general problem:
we can't guarantee to produce BEGIN blocks or C<use> declarations in
exactly the right place.  So if you use a module which affects compilation
(such as by over-riding keywords, overloading constants or whatever)
then the output code might not work as intended.

This is the most serious problem in Perl 5.20 and earlier.  Fixing this
required internal changes in Perl 5.22.

=item *

Some constants don't print correctly either with or without B<-d>.
For instance, neither B::Deparse nor Data::Dumper know how to print
dual-valued scalars correctly, as in:

    use constant E2BIG => ($!=7); $y = E2BIG; print $y, 0+$y;

    use constant H => { "#" => 1 }; H->{"#"};

=item *

An input file that uses source filtering probably won't be deparsed into
runnable code, because it will still include the B<use> declaration
for the source filtering module, even though the code that is
produced is already ordinary Perl which shouldn't be filtered again.

=item *

Optimized-away statements are rendered as
'???'.  This includes statements that
have a compile-time side-effect, such as the obscure

    my $x if 0;

which is not, consequently, deparsed correctly.

    foreach my $i (@_) { 0 }
  =>
    foreach my $i (@_) { '???' }

=item *

Lexical (my) variables declared in scopes external to a subroutine
appear in coderef2text output text as package variables.  This is a tricky
problem, as perl has no native facility for referring to a lexical variable
defined within a different scope, although L<PadWalker> is a good start.

See also L<Data::Dump::Streamer>, which combines B::Deparse and
L<PadWalker> to serialize closures properly.

=item *

There are probably many more bugs on non-ASCII platforms (EBCDIC).

=item *

Prior to Perl 5.22, lexical C<my> subroutines were not deparsed properly.
They were emitted as pure declarations, sometimes in the wrong place.
Lexical C<state> subroutines were not deparsed at all.

=back

=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, Robin Houston, Dave Mitchell,
Hugo van der Sanden, Gurusamy Sarathy, Nick Ing-Simmons, and Rafael
Garcia-Suarez.

=cut
Op_private.pm000064400000110022151004206260007202 0ustar00# -*- buffer-read-only: t -*-
#
#    lib/B/Op_private.pm
#
#    Copyright (C) 2014 by Larry Wall and others
#
#    You may distribute under the terms of either the GNU General Public
#    License or the Artistic License, as specified in the README file.
#
# !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
# This file is built by regen/opcode.pl from data in
# regen/op_private and pod embedded in regen/opcode.pl.
# Any changes made here will be lost!

=head1 NAME

B::Op_private -  OP op_private flag definitions

=head1 SYNOPSIS

    use B::Op_private;

    # flag details for bit 7 of OP_AELEM's op_private:
    my $name  = $B::Op_private::bits{aelem}{7}; # OPpLVAL_INTRO
    my $value = $B::Op_private::defines{$name}; # 128
    my $label = $B::Op_private::labels{$name};  # LVINTRO

    # the bit field at bits 5..6 of OP_AELEM's op_private:
    my $bf  = $B::Op_private::bits{aelem}{6};
    my $mask = $bf->{bitmask}; # etc

=head1 DESCRIPTION

This module provides four global hashes:

    %B::Op_private::bits
    %B::Op_private::defines
    %B::Op_private::labels
    %B::Op_private::ops_using

which contain information about the per-op meanings of the bits in the
op_private field.

=head2 C<%bits>

This is indexed by op name and then bit number (0..7). For single bit flags,
it returns the name of the define (if any) for that bit:

   $B::Op_private::bits{aelem}{7} eq 'OPpLVAL_INTRO';

For bit fields, it returns a hash ref containing details about the field.
The same reference will be returned for all bit positions that make
up the bit field; so for example these both return the same hash ref:

    $bitfield = $B::Op_private::bits{aelem}{5};
    $bitfield = $B::Op_private::bits{aelem}{6};

The general format of this hash ref is

    {
        # The bit range and mask; these are always present.
        bitmin        => 5,
        bitmax        => 6,
        bitmask       => 0x60,

        # (The remaining keys are optional)

        # The names of any defines that were requested:
        mask_def      => 'OPpFOO_MASK',
        baseshift_def => 'OPpFOO_SHIFT',
        bitcount_def  => 'OPpFOO_BITS',

        # If present, Concise etc will display the value with a 'FOO='
        # prefix. If it equals '-', then Concise will treat the bit
        # field as raw bits and not try to interpret it.
        label         => 'FOO',

        # If present, specifies the names of some defines and the
        # display labels that are used to assign meaning to particu-
        # lar integer values within the bit field; e.g. 3 is dis-
        # played as 'C'.
        enum          => [ qw(
                             1   OPpFOO_A  A
                             2   OPpFOO_B  B
                             3   OPpFOO_C  C
                         )],

    };


=head2 C<%defines>

This gives the value of every C<OPp> define, e.g.

    $B::Op_private::defines{OPpLVAL_INTRO} == 128;

=head2 C<%labels>

This gives the short display label for each define, as used by C<B::Concise>
and C<perl -Dx>, e.g.

    $B::Op_private::labels{OPpLVAL_INTRO} eq 'LVINTRO';

If the label equals '-', then Concise will treat the bit as a raw bit and
not try to display it symbolically.

=head2 C<%ops_using>

For each define, this gives a reference to an array of op names that use
the flag.

    @ops_using_lvintro = @{ $B::Op_private::ops_using{OPp_LVAL_INTRO} };

=cut

package B::Op_private;

our %bits;


our $VERSION = "5.026003";

$bits{$_}{3} = 'OPpENTERSUB_AMPER' for qw(entersub rv2cv);
$bits{$_}{6} = 'OPpENTERSUB_DB' for qw(entersub rv2cv);
$bits{$_}{2} = 'OPpENTERSUB_HASTARG' for qw(entersub rv2cv);
$bits{$_}{6} = 'OPpFLIP_LINENUM' for qw(flip flop);
$bits{$_}{1} = 'OPpFT_ACCESS' for qw(fteexec fteread ftewrite ftrexec ftrread ftrwrite);
$bits{$_}{4} = 'OPpFT_AFTER_t' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
$bits{$_}{2} = 'OPpFT_STACKED' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
$bits{$_}{3} = 'OPpFT_STACKING' for qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero);
$bits{$_}{1} = 'OPpHINT_STRICT_REFS' for qw(entersub multideref rv2av rv2cv rv2gv rv2hv rv2sv);
$bits{$_}{5} = 'OPpHUSH_VMSISH' for qw(dbstate nextstate);
$bits{$_}{1} = 'OPpITER_REVERSED' for qw(enteriter iter);
$bits{$_}{7} = 'OPpLVALUE' for qw(leave leaveloop);
$bits{$_}{6} = 'OPpLVAL_DEFER' for qw(aelem helem multideref);
$bits{$_}{7} = 'OPpLVAL_INTRO' for qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multideref padav padhv padrange padsv pushmark refassign rv2av rv2gv rv2hv rv2sv split);
$bits{$_}{2} = 'OPpLVREF_ELEM' for qw(lvref refassign);
$bits{$_}{3} = 'OPpLVREF_ITER' for qw(lvref refassign);
$bits{$_}{3} = 'OPpMAYBE_LVSUB' for qw(aassign aelem akeys aslice av2arylen avhvswitch helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec);
$bits{$_}{4} = 'OPpMAYBE_TRUEBOOL' for qw(padhv rv2hv);
$bits{$_}{7} = 'OPpOFFBYONE' for qw(caller runcv wantarray);
$bits{$_}{5} = 'OPpOPEN_IN_CRLF' for qw(backtick open);
$bits{$_}{4} = 'OPpOPEN_IN_RAW' for qw(backtick open);
$bits{$_}{7} = 'OPpOPEN_OUT_CRLF' for qw(backtick open);
$bits{$_}{6} = 'OPpOPEN_OUT_RAW' for qw(backtick open);
$bits{$_}{6} = 'OPpOUR_INTRO' for qw(enteriter gvsv rv2av rv2hv rv2sv split);
$bits{$_}{6} = 'OPpPAD_STATE' for qw(lvavref lvref padav padhv padsv pushmark refassign);
$bits{$_}{7} = 'OPpPV_IS_UTF8' for qw(dump goto last next redo);
$bits{$_}{6} = 'OPpREFCOUNTED' for qw(leave leaveeval leavesub leavesublv leavewrite);
$bits{$_}{2} = 'OPpSLICEWARNING' for qw(aslice hslice padav padhv rv2av rv2hv);
$bits{$_}{4} = 'OPpTARGET_MY' for qw(abs add atan2 chdir chmod chomp chown chr chroot concat cos crypt divide exec exp flock getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time unlink unshift utime wait waitpid);
$bits{$_}{5} = 'OPpTRANS_COMPLEMENT' for qw(trans transr);
$bits{$_}{7} = 'OPpTRANS_DELETE' for qw(trans transr);
$bits{$_}{0} = 'OPpTRANS_FROM_UTF' for qw(trans transr);
$bits{$_}{6} = 'OPpTRANS_GROWS' for qw(trans transr);
$bits{$_}{2} = 'OPpTRANS_IDENTICAL' for qw(trans transr);
$bits{$_}{3} = 'OPpTRANS_SQUASH' for qw(trans transr);
$bits{$_}{1} = 'OPpTRANS_TO_UTF' for qw(trans transr);
$bits{$_}{5} = 'OPpTRUEBOOL' for qw(padhv rv2hv);

my @bf = (
    {
        label     => '-',
        mask_def  => 'OPpARG1_MASK',
        bitmin    => 0,
        bitmax    => 0,
        bitmask   => 1,
    },
    {
        label     => '-',
        mask_def  => 'OPpARG2_MASK',
        bitmin    => 0,
        bitmax    => 1,
        bitmask   => 3,
    },
    {
        label     => 'offset',
        mask_def  => 'OPpAVHVSWITCH_MASK',
        bitmin    => 0,
        bitmax    => 1,
        bitmask   => 3,
    },
    {
        label     => '-',
        mask_def  => 'OPpARG3_MASK',
        bitmin    => 0,
        bitmax    => 2,
        bitmask   => 7,
    },
    {
        label     => '-',
        mask_def  => 'OPpARG4_MASK',
        bitmin    => 0,
        bitmax    => 3,
        bitmask   => 15,
    },
    {
        label     => 'range',
        mask_def  => 'OPpPADRANGE_COUNTMASK',
        bitcount_def => 'OPpPADRANGE_COUNTSHIFT',
        bitmin    => 0,
        bitmax    => 6,
        bitmask   => 127,
    },
    {
        label     => 'key',
        bitmin    => 0,
        bitmax    => 7,
        bitmask   => 255,
    },
    {
        mask_def  => 'OPpARGELEM_MASK',
        bitmin    => 1,
        bitmax    => 2,
        bitmask   => 6,
        enum      => [
            0, 'OPpARGELEM_SV', 'SV',
            1, 'OPpARGELEM_AV', 'AV',
            2, 'OPpARGELEM_HV', 'HV',
        ],
    },
    {
        mask_def  => 'OPpDEREF',
        bitmin    => 4,
        bitmax    => 5,
        bitmask   => 48,
        enum      => [
            1, 'OPpDEREF_AV', 'DREFAV',
            2, 'OPpDEREF_HV', 'DREFHV',
            3, 'OPpDEREF_SV', 'DREFSV',
        ],
    },
    {
        mask_def  => 'OPpLVREF_TYPE',
        bitmin    => 4,
        bitmax    => 5,
        bitmask   => 48,
        enum      => [
            0, 'OPpLVREF_SV', 'SV',
            1, 'OPpLVREF_AV', 'AV',
            2, 'OPpLVREF_HV', 'HV',
            3, 'OPpLVREF_CV', 'CV',
        ],
    },
);

@{$bits{aassign}}{6,5,4,1,0} = ('OPpASSIGN_COMMON_SCALAR', 'OPpASSIGN_COMMON_RC1', 'OPpASSIGN_COMMON_AGG', $bf[1], $bf[1]);
$bits{abs}{0} = $bf[0];
@{$bits{accept}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{add}}{1,0} = ($bf[1], $bf[1]);
$bits{aeach}{0} = $bf[0];
@{$bits{aelem}}{5,4,1,0} = ($bf[8], $bf[8], $bf[1], $bf[1]);
@{$bits{aelemfast}}{7,6,5,4,3,2,1,0} = ($bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6]);
@{$bits{aelemfast_lex}}{7,6,5,4,3,2,1,0} = ($bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6]);
$bits{akeys}{0} = $bf[0];
$bits{alarm}{0} = $bf[0];
$bits{and}{0} = $bf[0];
$bits{andassign}{0} = $bf[0];
$bits{anonconst}{0} = $bf[0];
@{$bits{anonhash}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{anonlist}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{argcheck}{0} = $bf[0];
$bits{argdefelem}{0} = $bf[0];
@{$bits{argelem}}{2,1,0} = ($bf[7], $bf[7], $bf[0]);
@{$bits{atan2}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{av2arylen}{0} = $bf[0];
$bits{avalues}{0} = $bf[0];
@{$bits{avhvswitch}}{1,0} = ($bf[2], $bf[2]);
$bits{backtick}{0} = $bf[0];
@{$bits{bind}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{binmode}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{bit_and}}{1,0} = ($bf[1], $bf[1]);
@{$bits{bit_or}}{1,0} = ($bf[1], $bf[1]);
@{$bits{bit_xor}}{1,0} = ($bf[1], $bf[1]);
@{$bits{bless}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{caller}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{chdir}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{chmod}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{chomp}{0} = $bf[0];
$bits{chop}{0} = $bf[0];
@{$bits{chown}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{chr}{0} = $bf[0];
$bits{chroot}{0} = $bf[0];
@{$bits{close}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{closedir}{0} = $bf[0];
$bits{complement}{0} = $bf[0];
@{$bits{concat}}{1,0} = ($bf[1], $bf[1]);
$bits{cond_expr}{0} = $bf[0];
@{$bits{connect}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{const}}{6,4,3,2,1} = ('OPpCONST_BARE', 'OPpCONST_ENTERED', 'OPpCONST_STRICT', 'OPpCONST_SHORTCIRCUIT', 'OPpCONST_NOVER');
@{$bits{coreargs}}{7,6,1,0} = ('OPpCOREARGS_PUSHMARK', 'OPpCOREARGS_SCALARMOD', 'OPpCOREARGS_DEREF2', 'OPpCOREARGS_DEREF1');
$bits{cos}{0} = $bf[0];
@{$bits{crypt}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{dbmclose}{0} = $bf[0];
@{$bits{dbmopen}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{defined}{0} = $bf[0];
@{$bits{delete}}{6,0} = ('OPpSLICE', $bf[0]);
@{$bits{die}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{divide}}{1,0} = ($bf[1], $bf[1]);
$bits{dofile}{0} = $bf[0];
$bits{dor}{0} = $bf[0];
$bits{dorassign}{0} = $bf[0];
$bits{dump}{0} = $bf[0];
$bits{each}{0} = $bf[0];
@{$bits{entereval}}{5,4,3,2,1,0} = ('OPpEVAL_RE_REPARSING', 'OPpEVAL_COPHH', 'OPpEVAL_BYTES', 'OPpEVAL_UNICODE', 'OPpEVAL_HAS_HH', $bf[0]);
$bits{entergiven}{0} = $bf[0];
$bits{enteriter}{3} = 'OPpITER_DEF';
@{$bits{entersub}}{5,4,0} = ($bf[8], $bf[8], 'OPpENTERSUB_INARGS');
$bits{entertry}{0} = $bf[0];
$bits{enterwhen}{0} = $bf[0];
@{$bits{enterwrite}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{eof}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{eq}}{1,0} = ($bf[1], $bf[1]);
@{$bits{exec}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{exists}}{6,0} = ('OPpEXISTS_SUB', $bf[0]);
@{$bits{exit}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{exp}{0} = $bf[0];
$bits{fc}{0} = $bf[0];
@{$bits{fcntl}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{fileno}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{flip}{0} = $bf[0];
@{$bits{flock}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{flop}{0} = $bf[0];
@{$bits{formline}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{ftatime}{0} = $bf[0];
$bits{ftbinary}{0} = $bf[0];
$bits{ftblk}{0} = $bf[0];
$bits{ftchr}{0} = $bf[0];
$bits{ftctime}{0} = $bf[0];
$bits{ftdir}{0} = $bf[0];
$bits{fteexec}{0} = $bf[0];
$bits{fteowned}{0} = $bf[0];
$bits{fteread}{0} = $bf[0];
$bits{ftewrite}{0} = $bf[0];
$bits{ftfile}{0} = $bf[0];
$bits{ftis}{0} = $bf[0];
$bits{ftlink}{0} = $bf[0];
$bits{ftmtime}{0} = $bf[0];
$bits{ftpipe}{0} = $bf[0];
$bits{ftrexec}{0} = $bf[0];
$bits{ftrowned}{0} = $bf[0];
$bits{ftrread}{0} = $bf[0];
$bits{ftrwrite}{0} = $bf[0];
$bits{ftsgid}{0} = $bf[0];
$bits{ftsize}{0} = $bf[0];
$bits{ftsock}{0} = $bf[0];
$bits{ftsuid}{0} = $bf[0];
$bits{ftsvtx}{0} = $bf[0];
$bits{fttext}{0} = $bf[0];
$bits{fttty}{0} = $bf[0];
$bits{ftzero}{0} = $bf[0];
@{$bits{ge}}{1,0} = ($bf[1], $bf[1]);
@{$bits{gelem}}{1,0} = ($bf[1], $bf[1]);
@{$bits{getc}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{getpeername}{0} = $bf[0];
@{$bits{getpgrp}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{getpriority}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{getsockname}{0} = $bf[0];
$bits{ggrgid}{0} = $bf[0];
$bits{ggrnam}{0} = $bf[0];
@{$bits{ghbyaddr}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{ghbyname}{0} = $bf[0];
@{$bits{glob}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{gmtime}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{gnbyaddr}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{gnbyname}{0} = $bf[0];
$bits{goto}{0} = $bf[0];
$bits{gpbyname}{0} = $bf[0];
@{$bits{gpbynumber}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{gpwnam}{0} = $bf[0];
$bits{gpwuid}{0} = $bf[0];
$bits{grepstart}{0} = $bf[0];
$bits{grepwhile}{0} = $bf[0];
@{$bits{gsbyname}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{gsbyport}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{gsockopt}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{gt}}{1,0} = ($bf[1], $bf[1]);
$bits{gv}{5} = 'OPpEARLY_CV';
@{$bits{helem}}{5,4,1,0} = ($bf[8], $bf[8], $bf[1], $bf[1]);
$bits{hex}{0} = $bf[0];
@{$bits{i_add}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_divide}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_eq}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_ge}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_gt}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_le}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_lt}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_modulo}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_multiply}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_ncmp}}{1,0} = ($bf[1], $bf[1]);
@{$bits{i_ne}}{1,0} = ($bf[1], $bf[1]);
$bits{i_negate}{0} = $bf[0];
$bits{i_postdec}{0} = $bf[0];
$bits{i_postinc}{0} = $bf[0];
$bits{i_predec}{0} = $bf[0];
$bits{i_preinc}{0} = $bf[0];
@{$bits{i_subtract}}{1,0} = ($bf[1], $bf[1]);
@{$bits{index}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{int}{0} = $bf[0];
@{$bits{ioctl}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{join}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{keys}{0} = $bf[0];
@{$bits{kill}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{last}{0} = $bf[0];
$bits{lc}{0} = $bf[0];
$bits{lcfirst}{0} = $bf[0];
@{$bits{le}}{1,0} = ($bf[1], $bf[1]);
$bits{leaveeval}{0} = $bf[0];
$bits{leavegiven}{0} = $bf[0];
@{$bits{leaveloop}}{1,0} = ($bf[1], $bf[1]);
$bits{leavesub}{0} = $bf[0];
$bits{leavesublv}{0} = $bf[0];
$bits{leavewhen}{0} = $bf[0];
$bits{leavewrite}{0} = $bf[0];
@{$bits{left_shift}}{1,0} = ($bf[1], $bf[1]);
$bits{length}{0} = $bf[0];
@{$bits{link}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{list}{6} = 'OPpLIST_GUESSED';
@{$bits{listen}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{localtime}{0} = $bf[0];
$bits{lock}{0} = $bf[0];
$bits{log}{0} = $bf[0];
@{$bits{lslice}}{1,0} = ($bf[1], $bf[1]);
$bits{lstat}{0} = $bf[0];
@{$bits{lt}}{1,0} = ($bf[1], $bf[1]);
$bits{lvavref}{0} = $bf[0];
@{$bits{lvref}}{5,4,0} = ($bf[9], $bf[9], $bf[0]);
$bits{mapstart}{0} = $bf[0];
$bits{mapwhile}{0} = $bf[0];
$bits{method}{0} = $bf[0];
$bits{method_named}{0} = $bf[0];
$bits{method_redir}{0} = $bf[0];
$bits{method_redir_super}{0} = $bf[0];
$bits{method_super}{0} = $bf[0];
@{$bits{mkdir}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{modulo}}{1,0} = ($bf[1], $bf[1]);
@{$bits{msgctl}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{msgget}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{msgrcv}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{msgsnd}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{multideref}}{5,4,0} = ('OPpMULTIDEREF_DELETE', 'OPpMULTIDEREF_EXISTS', $bf[0]);
@{$bits{multiply}}{1,0} = ($bf[1], $bf[1]);
@{$bits{nbit_and}}{1,0} = ($bf[1], $bf[1]);
@{$bits{nbit_or}}{1,0} = ($bf[1], $bf[1]);
@{$bits{nbit_xor}}{1,0} = ($bf[1], $bf[1]);
@{$bits{ncmp}}{1,0} = ($bf[1], $bf[1]);
$bits{ncomplement}{0} = $bf[0];
@{$bits{ne}}{1,0} = ($bf[1], $bf[1]);
$bits{negate}{0} = $bf[0];
$bits{next}{0} = $bf[0];
$bits{not}{0} = $bf[0];
$bits{oct}{0} = $bf[0];
$bits{once}{0} = $bf[0];
@{$bits{open}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{open_dir}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{or}{0} = $bf[0];
$bits{orassign}{0} = $bf[0];
$bits{ord}{0} = $bf[0];
@{$bits{pack}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{padrange}}{6,5,4,3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5], $bf[5]);
@{$bits{padsv}}{5,4} = ($bf[8], $bf[8]);
@{$bits{pipe_op}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{pop}{0} = $bf[0];
$bits{pos}{0} = $bf[0];
$bits{postdec}{0} = $bf[0];
$bits{postinc}{0} = $bf[0];
@{$bits{pow}}{1,0} = ($bf[1], $bf[1]);
$bits{predec}{0} = $bf[0];
$bits{preinc}{0} = $bf[0];
$bits{prototype}{0} = $bf[0];
@{$bits{push}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{quotemeta}{0} = $bf[0];
@{$bits{rand}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{range}{0} = $bf[0];
@{$bits{read}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{readdir}{0} = $bf[0];
$bits{readline}{0} = $bf[0];
$bits{readlink}{0} = $bf[0];
@{$bits{recv}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{redo}{0} = $bf[0];
$bits{ref}{0} = $bf[0];
@{$bits{refassign}}{5,4,1,0} = ($bf[9], $bf[9], $bf[1], $bf[1]);
$bits{refgen}{0} = $bf[0];
$bits{regcmaybe}{0} = $bf[0];
$bits{regcomp}{0} = $bf[0];
$bits{regcreset}{0} = $bf[0];
@{$bits{rename}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{repeat}}{6,1,0} = ('OPpREPEAT_DOLIST', $bf[1], $bf[1]);
$bits{require}{0} = $bf[0];
@{$bits{reset}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{reverse}}{3,0} = ('OPpREVERSE_INPLACE', $bf[0]);
$bits{rewinddir}{0} = $bf[0];
@{$bits{right_shift}}{1,0} = ($bf[1], $bf[1]);
@{$bits{rindex}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{rmdir}{0} = $bf[0];
$bits{rv2av}{0} = $bf[0];
@{$bits{rv2cv}}{7,5,0} = ('OPpENTERSUB_NOPAREN', 'OPpMAY_RETURN_CONSTANT', $bf[0]);
@{$bits{rv2gv}}{6,5,4,2,0} = ('OPpALLOW_FAKE', $bf[8], $bf[8], 'OPpDONT_INIT_GV', $bf[0]);
$bits{rv2hv}{0} = $bf[0];
@{$bits{rv2sv}}{5,4,0} = ($bf[8], $bf[8], $bf[0]);
@{$bits{sassign}}{7,6,1,0} = ('OPpASSIGN_CV_TO_GV', 'OPpASSIGN_BACKWARDS', $bf[1], $bf[1]);
@{$bits{sbit_and}}{1,0} = ($bf[1], $bf[1]);
@{$bits{sbit_or}}{1,0} = ($bf[1], $bf[1]);
@{$bits{sbit_xor}}{1,0} = ($bf[1], $bf[1]);
$bits{scalar}{0} = $bf[0];
$bits{schomp}{0} = $bf[0];
$bits{schop}{0} = $bf[0];
@{$bits{scmp}}{1,0} = ($bf[1], $bf[1]);
$bits{scomplement}{0} = $bf[0];
@{$bits{seek}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{seekdir}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{select}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{semctl}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{semget}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{semop}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{send}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{seq}}{1,0} = ($bf[1], $bf[1]);
@{$bits{setpgrp}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{setpriority}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sge}}{1,0} = ($bf[1], $bf[1]);
@{$bits{sgt}}{1,0} = ($bf[1], $bf[1]);
$bits{shift}{0} = $bf[0];
@{$bits{shmctl}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{shmget}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{shmread}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{shmwrite}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{shostent}{0} = $bf[0];
@{$bits{shutdown}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{sin}{0} = $bf[0];
@{$bits{sle}}{1,0} = ($bf[1], $bf[1]);
@{$bits{sleep}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{slt}}{1,0} = ($bf[1], $bf[1]);
@{$bits{smartmatch}}{1,0} = ($bf[1], $bf[1]);
@{$bits{sne}}{1,0} = ($bf[1], $bf[1]);
$bits{snetent}{0} = $bf[0];
@{$bits{socket}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sockpair}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sort}}{6,5,4,3,2,1,0} = ('OPpSORT_STABLE', 'OPpSORT_QSORT', 'OPpSORT_DESCEND', 'OPpSORT_INPLACE', 'OPpSORT_REVERSE', 'OPpSORT_INTEGER', 'OPpSORT_NUMERIC');
@{$bits{splice}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{split}}{4,3,2} = ('OPpSPLIT_ASSIGN', 'OPpSPLIT_LEX', 'OPpSPLIT_IMPLIM');
@{$bits{sprintf}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{sprotoent}{0} = $bf[0];
$bits{sqrt}{0} = $bf[0];
@{$bits{srand}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{srefgen}{0} = $bf[0];
@{$bits{sselect}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{sservent}{0} = $bf[0];
@{$bits{ssockopt}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{stat}{0} = $bf[0];
@{$bits{stringify}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{study}{0} = $bf[0];
$bits{substcont}{0} = $bf[0];
@{$bits{substr}}{4,2,1,0} = ('OPpSUBSTR_REPL_FIRST', $bf[3], $bf[3], $bf[3]);
@{$bits{subtract}}{1,0} = ($bf[1], $bf[1]);
@{$bits{symlink}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{syscall}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sysopen}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sysread}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{sysseek}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{system}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{syswrite}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{tell}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{telldir}{0} = $bf[0];
@{$bits{tie}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{tied}{0} = $bf[0];
@{$bits{truncate}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{uc}{0} = $bf[0];
$bits{ucfirst}{0} = $bf[0];
@{$bits{umask}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{undef}{0} = $bf[0];
@{$bits{unlink}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{unpack}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{unshift}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{untie}{0} = $bf[0];
@{$bits{utime}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{values}{0} = $bf[0];
@{$bits{vec}}{1,0} = ($bf[1], $bf[1]);
@{$bits{waitpid}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{warn}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
@{$bits{xor}}{1,0} = ($bf[1], $bf[1]);


our %defines = (
    OPpALLOW_FAKE            =>  64,
    OPpARG1_MASK             =>   1,
    OPpARG2_MASK             =>   3,
    OPpARG3_MASK             =>   7,
    OPpARG4_MASK             =>  15,
    OPpARGELEM_AV            =>   2,
    OPpARGELEM_HV            =>   4,
    OPpARGELEM_MASK          =>   6,
    OPpARGELEM_SV            =>   0,
    OPpASSIGN_BACKWARDS      =>  64,
    OPpASSIGN_COMMON_AGG     =>  16,
    OPpASSIGN_COMMON_RC1     =>  32,
    OPpASSIGN_COMMON_SCALAR  =>  64,
    OPpASSIGN_CV_TO_GV       => 128,
    OPpAVHVSWITCH_MASK       =>   3,
    OPpCONST_BARE            =>  64,
    OPpCONST_ENTERED         =>  16,
    OPpCONST_NOVER           =>   2,
    OPpCONST_SHORTCIRCUIT    =>   4,
    OPpCONST_STRICT          =>   8,
    OPpCOREARGS_DEREF1       =>   1,
    OPpCOREARGS_DEREF2       =>   2,
    OPpCOREARGS_PUSHMARK     => 128,
    OPpCOREARGS_SCALARMOD    =>  64,
    OPpDEREF                 =>  48,
    OPpDEREF_AV              =>  16,
    OPpDEREF_HV              =>  32,
    OPpDEREF_SV              =>  48,
    OPpDONT_INIT_GV          =>   4,
    OPpEARLY_CV              =>  32,
    OPpENTERSUB_AMPER        =>   8,
    OPpENTERSUB_DB           =>  64,
    OPpENTERSUB_HASTARG      =>   4,
    OPpENTERSUB_INARGS       =>   1,
    OPpENTERSUB_NOPAREN      => 128,
    OPpEVAL_BYTES            =>   8,
    OPpEVAL_COPHH            =>  16,
    OPpEVAL_HAS_HH           =>   2,
    OPpEVAL_RE_REPARSING     =>  32,
    OPpEVAL_UNICODE          =>   4,
    OPpEXISTS_SUB            =>  64,
    OPpFLIP_LINENUM          =>  64,
    OPpFT_ACCESS             =>   2,
    OPpFT_AFTER_t            =>  16,
    OPpFT_STACKED            =>   4,
    OPpFT_STACKING           =>   8,
    OPpHINT_STRICT_REFS      =>   2,
    OPpHUSH_VMSISH           =>  32,
    OPpITER_DEF              =>   8,
    OPpITER_REVERSED         =>   2,
    OPpLIST_GUESSED          =>  64,
    OPpLVALUE                => 128,
    OPpLVAL_DEFER            =>  64,
    OPpLVAL_INTRO            => 128,
    OPpLVREF_AV              =>  16,
    OPpLVREF_CV              =>  48,
    OPpLVREF_ELEM            =>   4,
    OPpLVREF_HV              =>  32,
    OPpLVREF_ITER            =>   8,
    OPpLVREF_SV              =>   0,
    OPpLVREF_TYPE            =>  48,
    OPpMAYBE_LVSUB           =>   8,
    OPpMAYBE_TRUEBOOL        =>  16,
    OPpMAY_RETURN_CONSTANT   =>  32,
    OPpMULTIDEREF_DELETE     =>  32,
    OPpMULTIDEREF_EXISTS     =>  16,
    OPpOFFBYONE              => 128,
    OPpOPEN_IN_CRLF          =>  32,
    OPpOPEN_IN_RAW           =>  16,
    OPpOPEN_OUT_CRLF         => 128,
    OPpOPEN_OUT_RAW          =>  64,
    OPpOUR_INTRO             =>  64,
    OPpPADRANGE_COUNTMASK    => 127,
    OPpPADRANGE_COUNTSHIFT   =>   7,
    OPpPAD_STATE             =>  64,
    OPpPV_IS_UTF8            => 128,
    OPpREFCOUNTED            =>  64,
    OPpREPEAT_DOLIST         =>  64,
    OPpREVERSE_INPLACE       =>   8,
    OPpSLICE                 =>  64,
    OPpSLICEWARNING          =>   4,
    OPpSORT_DESCEND          =>  16,
    OPpSORT_INPLACE          =>   8,
    OPpSORT_INTEGER          =>   2,
    OPpSORT_NUMERIC          =>   1,
    OPpSORT_QSORT            =>  32,
    OPpSORT_REVERSE          =>   4,
    OPpSORT_STABLE           =>  64,
    OPpSPLIT_ASSIGN          =>  16,
    OPpSPLIT_IMPLIM          =>   4,
    OPpSPLIT_LEX             =>   8,
    OPpSUBSTR_REPL_FIRST     =>  16,
    OPpTARGET_MY             =>  16,
    OPpTRANS_COMPLEMENT      =>  32,
    OPpTRANS_DELETE          => 128,
    OPpTRANS_FROM_UTF        =>   1,
    OPpTRANS_GROWS           =>  64,
    OPpTRANS_IDENTICAL       =>   4,
    OPpTRANS_SQUASH          =>   8,
    OPpTRANS_TO_UTF          =>   2,
    OPpTRUEBOOL              =>  32,
);

our %labels = (
    OPpALLOW_FAKE            => 'FAKE',
    OPpARGELEM_AV            => 'AV',
    OPpARGELEM_HV            => 'HV',
    OPpARGELEM_SV            => 'SV',
    OPpASSIGN_BACKWARDS      => 'BKWARD',
    OPpASSIGN_COMMON_AGG     => 'COM_AGG',
    OPpASSIGN_COMMON_RC1     => 'COM_RC1',
    OPpASSIGN_COMMON_SCALAR  => 'COM_SCALAR',
    OPpASSIGN_CV_TO_GV       => 'CV2GV',
    OPpCONST_BARE            => 'BARE',
    OPpCONST_ENTERED         => 'ENTERED',
    OPpCONST_NOVER           => 'NOVER',
    OPpCONST_SHORTCIRCUIT    => 'SHORT',
    OPpCONST_STRICT          => 'STRICT',
    OPpCOREARGS_DEREF1       => 'DEREF1',
    OPpCOREARGS_DEREF2       => 'DEREF2',
    OPpCOREARGS_PUSHMARK     => 'MARK',
    OPpCOREARGS_SCALARMOD    => '$MOD',
    OPpDEREF_AV              => 'DREFAV',
    OPpDEREF_HV              => 'DREFHV',
    OPpDEREF_SV              => 'DREFSV',
    OPpDONT_INIT_GV          => 'NOINIT',
    OPpEARLY_CV              => 'EARLYCV',
    OPpENTERSUB_AMPER        => 'AMPER',
    OPpENTERSUB_DB           => 'DBG',
    OPpENTERSUB_HASTARG      => 'TARG',
    OPpENTERSUB_INARGS       => 'INARGS',
    OPpENTERSUB_NOPAREN      => 'NO()',
    OPpEVAL_BYTES            => 'BYTES',
    OPpEVAL_COPHH            => 'COPHH',
    OPpEVAL_HAS_HH           => 'HAS_HH',
    OPpEVAL_RE_REPARSING     => 'REPARSE',
    OPpEVAL_UNICODE          => 'UNI',
    OPpEXISTS_SUB            => 'SUB',
    OPpFLIP_LINENUM          => 'LINENUM',
    OPpFT_ACCESS             => 'FTACCESS',
    OPpFT_AFTER_t            => 'FTAFTERt',
    OPpFT_STACKED            => 'FTSTACKED',
    OPpFT_STACKING           => 'FTSTACKING',
    OPpHINT_STRICT_REFS      => 'STRICT',
    OPpHUSH_VMSISH           => 'HUSH',
    OPpITER_DEF              => 'DEF',
    OPpITER_REVERSED         => 'REVERSED',
    OPpLIST_GUESSED          => 'GUESSED',
    OPpLVALUE                => 'LV',
    OPpLVAL_DEFER            => 'LVDEFER',
    OPpLVAL_INTRO            => 'LVINTRO',
    OPpLVREF_AV              => 'AV',
    OPpLVREF_CV              => 'CV',
    OPpLVREF_ELEM            => 'ELEM',
    OPpLVREF_HV              => 'HV',
    OPpLVREF_ITER            => 'ITER',
    OPpLVREF_SV              => 'SV',
    OPpMAYBE_LVSUB           => 'LVSUB',
    OPpMAYBE_TRUEBOOL        => 'BOOL?',
    OPpMAY_RETURN_CONSTANT   => 'CONST',
    OPpMULTIDEREF_DELETE     => 'DELETE',
    OPpMULTIDEREF_EXISTS     => 'EXISTS',
    OPpOFFBYONE              => '+1',
    OPpOPEN_IN_CRLF          => 'INCR',
    OPpOPEN_IN_RAW           => 'INBIN',
    OPpOPEN_OUT_CRLF         => 'OUTCR',
    OPpOPEN_OUT_RAW          => 'OUTBIN',
    OPpOUR_INTRO             => 'OURINTR',
    OPpPAD_STATE             => 'STATE',
    OPpPV_IS_UTF8            => 'UTF',
    OPpREFCOUNTED            => 'REFC',
    OPpREPEAT_DOLIST         => 'DOLIST',
    OPpREVERSE_INPLACE       => 'INPLACE',
    OPpSLICE                 => 'SLICE',
    OPpSLICEWARNING          => 'SLICEWARN',
    OPpSORT_DESCEND          => 'DESC',
    OPpSORT_INPLACE          => 'INPLACE',
    OPpSORT_INTEGER          => 'INT',
    OPpSORT_NUMERIC          => 'NUM',
    OPpSORT_QSORT            => 'QSORT',
    OPpSORT_REVERSE          => 'REV',
    OPpSORT_STABLE           => 'STABLE',
    OPpSPLIT_ASSIGN          => 'ASSIGN',
    OPpSPLIT_IMPLIM          => 'IMPLIM',
    OPpSPLIT_LEX             => 'LEX',
    OPpSUBSTR_REPL_FIRST     => 'REPL1ST',
    OPpTARGET_MY             => 'TARGMY',
    OPpTRANS_COMPLEMENT      => 'COMPL',
    OPpTRANS_DELETE          => 'DEL',
    OPpTRANS_FROM_UTF        => '<UTF',
    OPpTRANS_GROWS           => 'GROWS',
    OPpTRANS_IDENTICAL       => 'IDENT',
    OPpTRANS_SQUASH          => 'SQUASH',
    OPpTRANS_TO_UTF          => '>UTF',
    OPpTRUEBOOL              => 'BOOL',
);


our %ops_using = (
    OPpALLOW_FAKE            => [qw(rv2gv)],
    OPpASSIGN_BACKWARDS      => [qw(sassign)],
    OPpASSIGN_COMMON_AGG     => [qw(aassign)],
    OPpCONST_BARE            => [qw(const)],
    OPpCOREARGS_DEREF1       => [qw(coreargs)],
    OPpEARLY_CV              => [qw(gv)],
    OPpENTERSUB_AMPER        => [qw(entersub rv2cv)],
    OPpENTERSUB_INARGS       => [qw(entersub)],
    OPpENTERSUB_NOPAREN      => [qw(rv2cv)],
    OPpEVAL_BYTES            => [qw(entereval)],
    OPpEXISTS_SUB            => [qw(exists)],
    OPpFLIP_LINENUM          => [qw(flip flop)],
    OPpFT_ACCESS             => [qw(fteexec fteread ftewrite ftrexec ftrread ftrwrite)],
    OPpFT_AFTER_t            => [qw(ftatime ftbinary ftblk ftchr ftctime ftdir fteexec fteowned fteread ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned ftrread ftrwrite ftsgid ftsize ftsock ftsuid ftsvtx fttext fttty ftzero)],
    OPpHINT_STRICT_REFS      => [qw(entersub multideref rv2av rv2cv rv2gv rv2hv rv2sv)],
    OPpHUSH_VMSISH           => [qw(dbstate nextstate)],
    OPpITER_DEF              => [qw(enteriter)],
    OPpITER_REVERSED         => [qw(enteriter iter)],
    OPpLIST_GUESSED          => [qw(list)],
    OPpLVALUE                => [qw(leave leaveloop)],
    OPpLVAL_DEFER            => [qw(aelem helem multideref)],
    OPpLVAL_INTRO            => [qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multideref padav padhv padrange padsv pushmark refassign rv2av rv2gv rv2hv rv2sv split)],
    OPpLVREF_ELEM            => [qw(lvref refassign)],
    OPpMAYBE_LVSUB           => [qw(aassign aelem akeys aslice av2arylen avhvswitch helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr vec)],
    OPpMAYBE_TRUEBOOL        => [qw(padhv rv2hv)],
    OPpMULTIDEREF_DELETE     => [qw(multideref)],
    OPpOFFBYONE              => [qw(caller runcv wantarray)],
    OPpOPEN_IN_CRLF          => [qw(backtick open)],
    OPpOUR_INTRO             => [qw(enteriter gvsv rv2av rv2hv rv2sv split)],
    OPpPAD_STATE             => [qw(lvavref lvref padav padhv padsv pushmark refassign)],
    OPpPV_IS_UTF8            => [qw(dump goto last next redo)],
    OPpREFCOUNTED            => [qw(leave leaveeval leavesub leavesublv leavewrite)],
    OPpREPEAT_DOLIST         => [qw(repeat)],
    OPpREVERSE_INPLACE       => [qw(reverse)],
    OPpSLICE                 => [qw(delete)],
    OPpSLICEWARNING          => [qw(aslice hslice padav padhv rv2av rv2hv)],
    OPpSORT_DESCEND          => [qw(sort)],
    OPpSPLIT_ASSIGN          => [qw(split)],
    OPpSUBSTR_REPL_FIRST     => [qw(substr)],
    OPpTARGET_MY             => [qw(abs add atan2 chdir chmod chomp chown chr chroot concat cos crypt divide exec exp flock getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time unlink unshift utime wait waitpid)],
    OPpTRANS_COMPLEMENT      => [qw(trans transr)],
);

$ops_using{OPpASSIGN_COMMON_RC1} = $ops_using{OPpASSIGN_COMMON_AGG};
$ops_using{OPpASSIGN_COMMON_SCALAR} = $ops_using{OPpASSIGN_COMMON_AGG};
$ops_using{OPpASSIGN_CV_TO_GV} = $ops_using{OPpASSIGN_BACKWARDS};
$ops_using{OPpCONST_ENTERED} = $ops_using{OPpCONST_BARE};
$ops_using{OPpCONST_NOVER} = $ops_using{OPpCONST_BARE};
$ops_using{OPpCONST_SHORTCIRCUIT} = $ops_using{OPpCONST_BARE};
$ops_using{OPpCONST_STRICT} = $ops_using{OPpCONST_BARE};
$ops_using{OPpCOREARGS_DEREF2} = $ops_using{OPpCOREARGS_DEREF1};
$ops_using{OPpCOREARGS_PUSHMARK} = $ops_using{OPpCOREARGS_DEREF1};
$ops_using{OPpCOREARGS_SCALARMOD} = $ops_using{OPpCOREARGS_DEREF1};
$ops_using{OPpDONT_INIT_GV} = $ops_using{OPpALLOW_FAKE};
$ops_using{OPpENTERSUB_DB} = $ops_using{OPpENTERSUB_AMPER};
$ops_using{OPpENTERSUB_HASTARG} = $ops_using{OPpENTERSUB_AMPER};
$ops_using{OPpEVAL_COPHH} = $ops_using{OPpEVAL_BYTES};
$ops_using{OPpEVAL_HAS_HH} = $ops_using{OPpEVAL_BYTES};
$ops_using{OPpEVAL_RE_REPARSING} = $ops_using{OPpEVAL_BYTES};
$ops_using{OPpEVAL_UNICODE} = $ops_using{OPpEVAL_BYTES};
$ops_using{OPpFT_STACKED} = $ops_using{OPpFT_AFTER_t};
$ops_using{OPpFT_STACKING} = $ops_using{OPpFT_AFTER_t};
$ops_using{OPpLVREF_ITER} = $ops_using{OPpLVREF_ELEM};
$ops_using{OPpMAY_RETURN_CONSTANT} = $ops_using{OPpENTERSUB_NOPAREN};
$ops_using{OPpMULTIDEREF_EXISTS} = $ops_using{OPpMULTIDEREF_DELETE};
$ops_using{OPpOPEN_IN_RAW} = $ops_using{OPpOPEN_IN_CRLF};
$ops_using{OPpOPEN_OUT_CRLF} = $ops_using{OPpOPEN_IN_CRLF};
$ops_using{OPpOPEN_OUT_RAW} = $ops_using{OPpOPEN_IN_CRLF};
$ops_using{OPpSORT_INPLACE} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSORT_INTEGER} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSORT_NUMERIC} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSORT_QSORT} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSORT_REVERSE} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSORT_STABLE} = $ops_using{OPpSORT_DESCEND};
$ops_using{OPpSPLIT_IMPLIM} = $ops_using{OPpSPLIT_ASSIGN};
$ops_using{OPpSPLIT_LEX} = $ops_using{OPpSPLIT_ASSIGN};
$ops_using{OPpTRANS_DELETE} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRANS_FROM_UTF} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRANS_GROWS} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRANS_IDENTICAL} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRANS_SQUASH} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRANS_TO_UTF} = $ops_using{OPpTRANS_COMPLEMENT};
$ops_using{OPpTRUEBOOL} = $ops_using{OPpMAYBE_TRUEBOOL};

# ex: set ro: