line numbers are given % 64k
[p5sagit/p5-mst-13.2.git] / ext / B / B / Deparse.pm
index c373a69..3af74bc 100644 (file)
@@ -8,18 +8,18 @@
 
 package B::Deparse;
 use Carp;
-use B qw(class main_root main_start main_cv svref_2object opnumber cstring
+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
         OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
         OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY
         OPpCONST_ARYBASE OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER
         OPpSORT_REVERSE
-        SVf_IOK SVf_NOK SVf_ROK SVf_POK SVpad_OUR
-         CVf_METHOD CVf_LOCKED CVf_LVALUE
+        SVf_IOK SVf_NOK SVf_ROK SVf_POK SVpad_OUR SVf_FAKE
+         CVf_METHOD CVf_LOCKED CVf_LVALUE CVf_ASSERTION
         PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE PMf_SKIPWHITE
         PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED);
-$VERSION = 0.62;
+$VERSION = 0.63;
 use strict;
 use vars qw/$AUTOLOAD/;
 use warnings ();
@@ -106,6 +106,10 @@ use warnings ();
 # - 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.)
 
 # Todo:
 #  (See also BUGS section at the end of this file)
@@ -322,7 +326,14 @@ sub begin_is_use {
 
        return unless $self->const_sv($constop)->PV eq $module;
        $constop = $constop->sibling;
-       $version = $self->const_sv($constop)->int_value;
+       $version = $self->const_sv($constop);
+       if (class($version) ne "PVMG") {
+           # version is either an integer or a double
+           $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->const_sv($constop)->PV ne "VERSION";
@@ -538,20 +549,21 @@ sub compile {
        my $self = B::Deparse->new(@args);
        # First deparse command-line args
        if (defined $^I) { # deparse -i
-           print q(BEGIN { $^I = ).cstring($^I).qq(; }\n);
+           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 = cstring($/) || 'undef';
-           my $bs = cstring($O::savebackslash) || 'undef';
+           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 @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 : ();
-       for my $block (@BEGINs, @INITs, @ENDs) {
+       for my $block (@BEGINs, @CHECKs, @INITs, @ENDs) {
            $self->todo($block, 0);
        }
        $self->stash_subs();
@@ -582,7 +594,7 @@ sub compile {
 sub coderef2text {
     my $self = shift;
     my $sub = shift;
-    croak "Usage: ->coderef2text(CODEREF)" unless ref($sub) eq "CODE";
+    croak "Usage: ->coderef2text(CODEREF)" unless UNIVERSAL::isa($sub, "CODE");
 
     $self->init();
     return $self->indent($self->deparse_sub(svref_2object($sub)));
@@ -743,11 +755,12 @@ Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
     if ($cv->FLAGS & SVf_POK) {
        $proto = "(". $cv->PV . ") ";
     }
-    if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) {
+    if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE|CVf_ASSERTION)) {
         $proto .= ": ";
         $proto .= "lvalue " if $cv->CvFLAGS & CVf_LVALUE;
         $proto .= "locked " if $cv->CvFLAGS & CVf_LOCKED;
         $proto .= "method " if $cv->CvFLAGS & CVf_METHOD;
+        $proto .= "assertion " if $cv->CvFLAGS & CVf_ASSERTION;
     }
 
     local($self->{'curcv'}) = $cv;
@@ -796,7 +809,8 @@ sub deparse_format {
                = @$self{qw'curstash warnings hints'};
     my $op = $form->ROOT;
     my $kid;
-    return "\f." if $op->first->name eq 'stub';
+    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
@@ -908,6 +922,10 @@ sub maybe_local {
     if ($op->private & (OPpLVAL_INTRO|$our_intro)
        and not $self->{'avoid_local'}{$$op}) {
        my $our_local = ($op->private & OPpLVAL_INTRO) ? "local" : "our";
+       if( $our_local eq 'our' ) {
+           die "Unexpected our($text)\n" unless $text =~ /^\W(\w+::)*\w+\z/;
+           $text =~ s/(\w+::)+//; 
+       }
         if (want_scalar($op)) {
            return "$our_local $text";
        } else {
@@ -963,6 +981,8 @@ sub AUTOLOAD {
     }
 }
 
+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
@@ -1073,7 +1093,8 @@ sub gv_name {
 Carp::confess() if $gv->isa("B::CV");
     my $stash = $gv->STASH->NAME;
     my $name = $gv->SAFENAME;
-    if ($stash eq $self->{'curstash'} or $globalnames{$name}
+    if (($stash eq 'main' && $globalnames{$name})
+       or ($stash eq $self->{'curstash'} && !$globalnames{$name})
        or $name =~ /^[^A-Za-z_]/)
     {
        $stash = "";
@@ -1121,7 +1142,10 @@ sub lex_in_scope {
 sub populate_curcvlex {
     my $self = shift;
     for (my $cv = $self->{'curcv'}; class($cv) eq "CV"; $cv = $cv->OUTSIDE) {
-       my @padlist = $cv->PADLIST->ARRAY;
+       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) {
@@ -1132,8 +1156,10 @@ sub populate_curcvlex {
                next;
            }
             my $name = $ns[$i]->PVX;
-           my $seq_st = $ns[$i]->NVX;
-           my $seq_en = int($ns[$i]->IVX);
+           my ($seq_st, $seq_en) =
+               ($ns[$i]->FLAGS & SVf_FAKE)
+                   ? (0, 999999)
+                   : ($ns[$i]->NVX, $ns[$i]->IVX);
 
            push @{$self->{'curcvlex'}{$name}}, [$seq_st, $seq_en];
        }
@@ -1258,7 +1284,7 @@ sub declare_warnings {
     elsif (($to & WARN_MASK) eq "\0"x length($to)) {
        return "no warnings;\n";
     }
-    return "BEGIN {\${^WARNING_BITS} = ".cstring($to)."}\n";
+    return "BEGIN {\${^WARNING_BITS} = ".perlstring($to)."}\n";
 }
 
 sub declare_hints {
@@ -1943,6 +1969,7 @@ sub logop {
 
 sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }
 sub pp_or  { logop(@_, "or",  2, "||", 10, "unless") }
+sub pp_dor { logop(@_, "err", 2, "//", 10, "") }
 
 # xor is syntactically a logop, but it's really a binop (contrary to
 # old versions of opcode.pl). Syntax is what matters here.
@@ -1959,7 +1986,8 @@ sub logassignop {
 }
 
 sub pp_andassign { logassignop(@_, "&&=") }
-sub pp_orassign { logassignop(@_, "||=") }
+sub pp_orassign  { logassignop(@_, "||=") }
+sub pp_dorassign { logassignop(@_, "//=") }
 
 sub listop {
     my $self = shift;
@@ -1969,6 +1997,7 @@ sub listop {
     my $kid = $op->first->sibling;
     return $name if null $kid;
     my $first;
+    $name = "socketpair" if $name eq "sockpair";
     if (defined prototype("CORE::$name")
        && prototype("CORE::$name") =~ /^;?\*/
        && $kid->name eq "rv2gv") {
@@ -2167,7 +2196,7 @@ sub mapop {
     $kid = $kid->sibling;
     for (; !null($kid); $kid = $kid->sibling) {
        $expr = $self->deparse($kid, 6);
-       push @exprs, $expr if $expr;
+       push @exprs, $expr if defined $expr;
     }
     return $self->maybe_parens_func($name, $code . join(", ", @exprs), $cx, 5);
 }
@@ -2294,7 +2323,7 @@ sub loop_common {
     my $body;
     my $cond = undef;
     if ($kid->name eq "lineseq") { # bare or infinite loop 
-       if (is_state $kid->last) { # infinite
+       if ($kid->last->name eq "unstack") { # infinite
            $head = "while (1) "; # Can't use for(;;) if there's a continue
            $cond = "";
        } else {
@@ -2317,17 +2346,14 @@ sub loop_common {
                $var = $self->pp_threadsv($enter, 1);
            } else { # regular my() variable
                $var = $self->pp_padsv($enter, 1);
-               if ($self->padname_sv($enter->targ)->IVX ==
-                   $kid->first->first->sibling->last->cop_seq)
-               {
-                   # If the scope of this variable closes at the last
-                   # statement of the loop, it must have been
-                   # declared here.
-                   $var = "my " . $var;
-               }
            }
        } elsif ($var->name eq "rv2gv") {
            $var = $self->pp_rv2sv($var, 1);
+           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);
        }
@@ -2343,18 +2369,18 @@ sub loop_common {
        return "{;}"; # {} could be a hashref
     }
     # If there isn't a continue block, then the next pointer for the loop
-    # will point to the unstack, which is kid's penultimate child, except
+    # 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 third-to-last child in the continue
+    # 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;
-    if ($$cont_start != $$op && ${$cont_start->sibling} != ${$body->last}) {
+    if ($$cont_start != $$op && ${$cont_start} != ${$body->last}) {
        if ($bare) {
            $cont = $body->last;
        } else {
            $cont = $body->first;
-           while (!null($cont->sibling->sibling->sibling)) {
+           while (!null($cont->sibling->sibling)) {
                $cont = $cont->sibling;
            }
        }
@@ -2406,7 +2432,7 @@ BEGIN { eval "sub OP_LIST () {" . opnumber("list") . "}" }
 
 sub pp_null {
     my $self = shift;
-    my($op, $cx) = @_;
+    my($op, $cx, $flags) = @_;
     if (class($op) eq "OP") {
        # old value is lost
        return $self->{'ex_const'} if $op->targ == OP_CONST;
@@ -2429,7 +2455,12 @@ sub pp_null {
                                   . $self->deparse($op->first->sibling, 20),
                                   $cx, 20);
     } elsif ($op->flags & OPf_SPECIAL && $cx == 0 && !$op->targ) {
-       return "do {\n\t". $self->deparse($op->first, $cx) ."\n\b};";
+       if ($flags) {
+           return $self->deparse($op->first, $cx);
+       }
+       else {
+           return "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
@@ -3001,7 +3032,7 @@ sub re_uninterp {
           | \\[uUlLQE]
           )
 
-       /length($4) ? "$1$2$4" : "$1$2\\$3"/xeg;
+       /defined($4) && length($4) ? "$1$2$4" : "$1$2\\$3"/xeg;
 
     return $str;
 }
@@ -3025,29 +3056,64 @@ sub re_uninterp_extended {
             | \#[^\n]*            #     (skip over comments)
             )
           | [\$\@]
-            (?!\||\)|\(|$)
+            (?!\||\)|\(|$|\s)
           | \\[uUlLQE]
           )
 
-       /length($4) ? "$1$2$4" : "$1$2\\$3"/xeg;
+       /defined($4) && length($4) ? "$1$2$4" : "$1$2\\$3"/xeg;
 
     return $str;
 }
 }
 
+my %unctrl = # portable to to EBCDIC
+    (
+     "\c@" => '\c@',   # unused
+     "\cA" => '\cA',
+     "\cB" => '\cB',
+     "\cC" => '\cC',
+     "\cD" => '\cD',
+     "\cE" => '\cE',
+     "\cF" => '\cF',
+     "\cG" => '\cG',
+     "\cH" => '\cH',
+     "\cI" => '\cI',
+     "\cJ" => '\cJ',
+     "\cK" => '\cK',
+     "\cL" => '\cL',
+     "\cM" => '\cM',
+     "\cN" => '\cN',
+     "\cO" => '\cO',
+     "\cP" => '\cP',
+     "\cQ" => '\cQ',
+     "\cR" => '\cR',
+     "\cS" => '\cS',
+     "\cT" => '\cT',
+     "\cU" => '\cU',
+     "\cV" => '\cV',
+     "\cW" => '\cW',
+     "\cX" => '\cX',
+     "\cY" => '\cY',
+     "\cZ" => '\cZ',
+     "\c[" => '\c[',   # unused
+     "\c\\" => '\c\\', # unused
+     "\c]" => '\c]',   # unused
+     "\c_" => '\c_',   # unused
+    );
+
 # 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/(.)/ord($1) > 255 ? sprintf("\\x{%x}", ord($1)) : $1/eg;
     $str =~ s/\a/\\a/g;
-#    $str =~ s/\cH/\\b/g; # \b means someting different in a regex 
+#    $str =~ s/\cH/\\b/g; # \b means something different in a regex 
     $str =~ s/\t/\\t/g;
     $str =~ s/\n/\\n/g;
     $str =~ s/\e/\\e/g;
     $str =~ s/\f/\\f/g;
     $str =~ s/\r/\\r/g;
-    $str =~ s/([\cA-\cZ])/'\\c' . chr(ord('@') + ord($1))/ge;
-    $str =~ s/([\0\033-\037\177-\377])/'\\' . sprintf("%03o", ord($1))/ge;
+    $str =~ s/([\cA-\cZ])/$unctrl{$1}/ge;
+    $str =~ s/([[:^print:]])/sprintf("\\%03o", ord($1))/ge;
     return $str;
 }
 
@@ -3055,8 +3121,9 @@ sub escape_str { # ASCII, UTF8
 # Leave whitespace unmangled.
 sub escape_extended_re {
     my($str) = @_;
-    $str =~ s/(.)/ord($1)>255 ? sprintf("\\x{%x}", ord($1)) : $1/eg;
-    $str =~ s/([\0\033-\037\177-\377])/'\\' . sprintf("%03o", ord($1))/ge;
+    $str =~ s/(.)/ord($1) > 255 ? sprintf("\\x{%x}", ord($1)) : $1/eg;
+    $str =~ s/([[:^print:]])/
+       ($1 =~ y! \t\n!!) ? $1 : sprintf("\\%03o", ord($1))/ge;
     $str =~ s/\n/\n\f/g;
     return $str;
 }
@@ -3074,7 +3141,7 @@ sub re_unback {
     my($str) = @_;
 
     # the insane complexity here is due to the behaviour of "\c\"
-    $str =~ s/(^|[^\\]|\\c\\)(?<!\\c)\\(\\\\)*(?=[\0-\031\177-\377])/$1$2/g;
+    $str =~ s/(^|[^\\]|\\c\\)(?<!\\c)\\(\\\\)*(?=[[:^print:]])/$1$2/g;
     return $str;
 }
 
@@ -3125,7 +3192,7 @@ sub single_delim {
 sub const {
     my $sv = shift;
     if (class($sv) eq "SPECIAL") {
-       return ('undef', '1', '0')[$$sv-1]; # sv_undef, sv_yes, sv_no
+       return ('undef', '1', '(!1)')[$$sv-1]; # sv_undef, sv_yes, sv_no
     } elsif (class($sv) eq "NULL") {
        return 'undef';
     } elsif ($sv->FLAGS & SVf_IOK) {
@@ -3187,10 +3254,10 @@ sub dq {
        my $first = $self->dq($op->first);
        my $last  = $self->dq($op->last);
 
-       # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]"
+       # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]", "$foo\::bar"
        ($last =~ /^[A-Z\\\^\[\]_?]/ &&
            $first =~ s/([\$@])\^$/${1}{^}/)  # "${^}W" etc
-           || ($last =~ /^[{\[\w_]/ &&
+           || ($last =~ /^[:'{\[\w_]/ &&
                $first =~ s/([\$@])([A-Za-z_]\w*)$/${1}{$2}/);
 
        return $first . $last;
@@ -3519,6 +3586,7 @@ sub re_dq {
 
 sub pure_string {
     my ($self, $op) = @_;
+    return 0 if null $op;
     my $type = $op->name;
 
     if ($type eq 'const') {
@@ -3687,7 +3755,7 @@ sub pp_subst {
            $flags .= "e";
        }
        if ($op->pmflags & PMf_EVAL) {
-           $repl = $self->deparse($repl, 0);
+           $repl = $self->deparse($repl, 0, 1);
        } else {
            $repl = $self->dq($repl);   
        }