This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
authorJarkko Hietaniemi <jhi@iki.fi>
Tue, 18 Feb 2003 14:46:18 +0000 (14:46 +0000)
committerJarkko Hietaniemi <jhi@iki.fi>
Tue, 18 Feb 2003 14:46:18 +0000 (14:46 +0000)
[ 18280]
Integrate from the maint-5.8/ branch :
changes 18219, 18236, 18242-3, 18247-8,
18253-5, 18257, 18273-6

[ 18740]
Re: -Os for Darwin why?
From: schwern@pobox.com
Date: tis feb 18, 2003  04:14:03 Europe/Stockholm
Message-Id: <20030217191403.A17553@ttul.org>

[ 18737]
Subject: [PATCH] Re: [perl #21261] B::Terse not outputting correct constants or variable names
From: Stephen McCamant <smcc@mit.edu>
Date: Mon, 17 Feb 2003 19:34:36 -0500
Date: Mon, 17 Feb 2003 19:34:36 -0500
Message-ID: <15953.32668.277063.470885@syllepsis.MIT.EDU>

[ 18723]
Subject: Re: [perl #20798] foo(eval {}) crashes Perl 5.8
From: Enache Adrian <enache@rdslink.ro>
Date: Sun, 16 Feb 2003 00:05:10 +0200
Message-ID: <20030215220510.GB893@ratsnest.hole>

[ 18722]
outdent else-if chain in scope()

[ 18721]
Subject: [PATCH] arcane tainting bug in vms.c
From: "Craig A. Berry" <craigberry@mac.com>
Date: Sat, 15 Feb 2003 12:29:03 -0600
Message-ID: <3E4E86EF.8090609@mac.com>

[ 18720]
restrict PERL_PRESERVE_IVUV to things that should really give an
integer, but extend to runtime. Based on:
Subject: Re: [perl #20827] Unexpected scientific notation.
From: hv@crypt.org
Date: Wed, 12 Feb 2003 03:12:43 +0000
Message-Id: <200302120312.h1C3ChS02613@crypt.compulink.co.uk>

[ 18708]
Subject: Re: [perl #20912] UTF8 related glitch + fix
From: Enache Adrian <enache@rdslink.ro>
Date: Sat, 15 Feb 2003 00:37:40 +0200
Message-ID: <20030214223740.GA13575@ratsnest.hole>

[ 18707]
Subject: [doc patch] ext/threads/shared/shared.pm
From: Stas Bekman <stas@stason.org>
Date: Fri, 14 Feb 2003 11:12:39 +1100
Message-ID: <3E4C3477.7030306@stason.org>

[ 18706]
Subject: Re: perlvar phrasing clarification for $^S
From: "Iain 'Spoon' Truskett" <perl@dellah.anu.edu.au>
Date: Fri, 14 Feb 2003 10:12:00 +1100
Message-ID: <20030213231200.GE16300@ouroboros.anu.edu.au>

[ 18705]
Subject: Re: [perl #20933] \substr reuses lvalues (sometimes)
From: Dave Mitchell <davem@fdgroup.com>
Date: Fri, 14 Feb 2003 22:48:27 +0000
Message-ID: <20030214224827.B6783@fdgroup.com>

with tests:
From: Slaven Rezic <slaven@rezic.de>
Date: 14 Feb 2003 20:23:20 +0100
Message-ID: <87bs1e4qfr.fsf@vran.herceg.de>

[ 18704]
Subject: Re: overriding builtins quirk
From: Jerrad Pierce <belg4mit@MIT.EDU>
Date: Fri, 14 Feb 2003 09:28:13 -0500
Message-Id: <200302141428.JAA25752@cathedral-seven.mit.edu>

[ 18703]
Subject: Re: trying to fix #20154, #20357
From: Enache Adrian <enache@rdslink.ro>
Date: Sat, 8 Feb 2003 21:05:14 +0200
Message-ID: <20030208190514.GA866@ratsnest.hole>
(fixes #19061 as well)
p4raw-link: @18740 on //depot/perl: 14c260282869b514252d84245cb9a2c34eb7d421
p4raw-link: @18737 on //depot/perl: 31b49ad407e88940fdaef710e5f6a42665a067d8
p4raw-link: @18723 on //depot/perl: 4927db4444d4255bf5c9a54ba1d153bb533bd274
p4raw-link: @18722 on //depot/perl: fdb2241864c257e44490544064b09a293414e55f
p4raw-link: @18721 on //depot/perl: ec618cdf8cd188a382b8a5ab7751b8c7e9ef80c2
p4raw-link: @18720 on //depot/perl: 52a96ae66a5b0cd12cd52516c48cc6bf774e2038
p4raw-link: @18708 on //depot/perl: 3b0d546b549c81b8fd7281af083002e289e306d6
p4raw-link: @18707 on //depot/perl: 72ac79b36fc2613b9b03b8424fe60fdaa5759b16
p4raw-link: @18706 on //depot/perl: fa05a9fd14fa1e936b4708399d5cb3873024a775
p4raw-link: @18705 on //depot/perl: 24aef97f7fec4668a5731fc6d5179ebebd43f183
p4raw-link: @18704 on //depot/perl: 163e3a99f83605ff107fb86a86c7dd9dc9dece8f
p4raw-link: @18703 on //depot/perl: 33d34e4c563f3e0b3627fb43d2e2a2ef278a273a
p4raw-link: @18280 on //depot/perl: 3a2263fe90d1c0e6c8f9368f10e6672379a975a2

p4raw-id: //depot/maint-5.8/perl@18744
p4raw-integrated: from //depot/perl@18743 'copy in' t/op/substr.t
(@9270..) t/op/goto.t (@10643..) ext/B/B/Terse.pm (@13034..)
ext/B/B/Bblock.pm (@13697..) t/op/vec.t (@14887..)
ext/B/t/terse.t (@16882..) pod/perlsub.pod (@17220..)
ext/threads/shared/shared.pm (@17810..) t/op/lc.t (@18266..)
t/op/split.t (@18280..) 'edit in' pp.c (@18708..) 'merge in'
vms/vms.c (@18030..) ext/B/B.xs (@18220..) hints/darwin.sh
(@18406..) ext/B/B/Concise.pm (@18694..)
p4raw-integrated: from //depot/perl@18723 'edit in' op.c (@18722..)
p4raw-integrated: from //depot/perl@18706 'merge in' pod/perlvar.pod
(@18490..)
p4raw-integrated: from //depot/perl@18703 'merge in' pp_ctl.c
(@18688..)

18 files changed:
ext/B/B.xs
ext/B/B/Bblock.pm
ext/B/B/Concise.pm
ext/B/B/Terse.pm
ext/B/t/terse.t
ext/threads/shared/shared.pm
hints/darwin.sh
op.c
pod/perlsub.pod
pod/perlvar.pod
pp.c
pp_ctl.c
t/op/goto.t
t/op/lc.t
t/op/split.t
t/op/substr.t
t/op/vec.t
vms/vms.c

index c9ce77c..f8bae0e 100644 (file)
@@ -95,7 +95,8 @@ cc_opclass(pTHX_ OP *o)
        return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
 
 #ifdef USE_ITHREADS
-    if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
+    if (o->op_type == OP_GV || o->op_type == OP_GVSV ||
+       o->op_type == OP_AELEMFAST || o->op_type == OP_RCATLINE)
        return OPc_PADOP;
 #endif
 
index 624bae4..35a80ea 100644 (file)
@@ -10,7 +10,7 @@ use B qw(peekop walkoptree walkoptree_exec
         main_root main_start svref_2object
          OPf_SPECIAL OPf_STACKED );
 
-use B::Terse;
+use B::Concise qw(concise_cv concise_main set_style_standard);
 use strict;
 
 my $bblock;
@@ -64,8 +64,6 @@ sub walk_bblocks {
        }
        printf "    %s\n", peekop($lastop);
     }
-    print "-------\n";
-    walkoptree_exec($start, "terse");
 }
 
 sub walk_bblocks_obj {
@@ -140,10 +138,19 @@ sub compile {
                $objname = "main::$objname" unless $objname =~ /::/;
                eval "walk_bblocks_obj(\\&$objname)";
                die "walk_bblocks_obj(\\&$objname) failed: $@" if $@;
+               print "-------\n";
+               set_style_standard("terse");
+               eval "concise_cv('exec', \\&$objname)";
+               die "concise_cv('exec', \\&$objname) failed: $@" if $@;
            }
        }
     } else {
-       return sub { walk_bblocks(main_root, main_start) };
+       return sub {
+           walk_bblocks(main_root, main_start);
+           print "-------\n";
+           set_style_standard("terse");
+           concise_main("exec");
+       };
     }
 }
 
index 0411c65..b6705bc 100644 (file)
@@ -8,12 +8,13 @@ use warnings;
 
 use Exporter ();
 
-our $VERSION   = "0.54";
+our $VERSION   = "0.55";
 our @ISA       = qw(Exporter);
-our @EXPORT_OK = qw(set_style add_callback);
+our @EXPORT_OK = qw(set_style set_style_standard add_callback
+                   concise_cv concise_main);
 
 use B qw(class ppname main_start main_root main_cv cstring svref_2object
-        SVf_IOK SVf_NOK SVf_POK OPf_KIDS);
+        SVf_IOK SVf_NOK SVf_POK SVf_IVisUV OPf_KIDS);
 
 my %style = 
   ("terse" =>
@@ -51,6 +52,11 @@ sub set_style {
     ($format, $gotofmt, $treefmt) = @_;
 }
 
+sub set_style_standard {
+    my($name) = @_;
+    set_style(@{$style{$name}});
+}
+
 sub add_callback {
     push @callbacks, @_;
 }
@@ -69,6 +75,23 @@ sub concise_cv {
     }
 }
 
+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 tree(main_root, 0);
+    } elsif ($order eq "basic") {
+       return if class(main_root) eq "NULL";
+       walk_topdown(main_root,
+                    sub { $_[0]->concise($_[1]) }, 0);
+    }
+}
+
 my $start_sym = "\e(0"; # "\cN" sometimes also works
 my $end_sym   = "\e(B"; # "\cO" respectively
 
@@ -85,7 +108,7 @@ my $big_endian = 1;
 
 my $order = "basic";
 
-set_style(@{$style{concise}});
+set_style_standard("concise");
 
 sub compile {
     my @options = grep(/^-/, @_);
@@ -131,19 +154,7 @@ sub compile {
        }
        if (!@args or $do_main) {
            print "main program:\n" if $do_main;
-           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 tree(main_root, 0);
-           } elsif ($order eq "basic") {
-               return if class(main_root) eq "NULL";
-               walk_topdown(main_root,
-                            sub { $_[0]->concise($_[1]) }, 0);
-           }
+           concise_main($order);
        }
     }
 }
@@ -216,7 +227,7 @@ sub walk_topdown {
            walk_topdown($kid, $sub, $level + 1);
        }
     }
-    if (class($op) eq "PMOP" and $ {$op->pmreplroot}
+    if (class($op) eq "PMOP" and $op->pmreplroot and $ {$op->pmreplroot}
        and $op->pmreplroot->isa("B::OP")) {
        walk_topdown($op->pmreplroot, $sub, $level + 1);
     }
@@ -375,6 +386,8 @@ sub private_flags {
 sub concise_sv {
     my($sv, $hr) = @_;
     $hr->{svclass} = class($sv);
+    $hr->{svclass} = "UV"
+      if $hr->{svclass} eq "IV" and $sv->FLAGS & SVf_IVisUV;
     $hr->{svaddr} = sprintf("%#x", $$sv);
     if ($hr->{svclass} eq "GV") {
        my $gv = $sv;
@@ -396,9 +409,11 @@ sub concise_sv {
        } elsif ($sv->FLAGS & SVf_NOK) {
            $hr->{svval} .= $sv->NV;
        } elsif ($sv->FLAGS & SVf_IOK) {
-           $hr->{svval} .= $sv->IV;
+           $hr->{svval} .= $sv->int_value;
        } elsif ($sv->FLAGS & SVf_POK) {
            $hr->{svval} .= cstring($sv->PV);
+       } elsif (class($sv) eq "HV") {
+           $hr->{svval} .= 'HASH';
        }
        return $hr->{svclass} . " " .  $hr->{svval};
     }
@@ -439,7 +454,7 @@ sub concise_op {
        }
        my $pmreplroot = $op->pmreplroot;
        my $pmreplstart;
-       if ($$pmreplroot && $pmreplroot->isa("B::GV")) {
+       if ($pmreplroot && $$pmreplroot && $pmreplroot->isa("B::GV")) {
            # with C<@stash_array = split(/pat/, str);>,
            #  *stash_array is stored in pmreplroot.
            $h{arg} = "($precomp => \@" . $pmreplroot->NAME . ")";
@@ -478,6 +493,9 @@ sub concise_op {
        } else {
            $h{arg} = "(" . concise_sv($op->sv, \%h) . ")";
        }
+    } elsif ($h{class} eq "PADOP") {
+       my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->padix];
+       $h{arg} = "[" . concise_sv($sv, \%h) . "]";
     }
     $h{seq} = $h{hyphseq} = seq($op);
     $h{seq} = "" if $h{seq} eq "-";
@@ -513,6 +531,30 @@ sub B::OP::concise {
     print 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) {
+       my $h = {"seq" => seq($lastnext), "class" => class($lastnext),
+                "addr" => sprintf("%#x", $$lastnext)};
+       print fmt_line($h, $style{"terse"}[1], $level+1);
+    }
+    $lastnext = $op->next;
+    print concise_op($op, $level, $style{"terse"}[0]);
+}
+
 sub tree {
     my $op = shift;
     my $level = shift;
@@ -1007,11 +1049,14 @@ 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.
 
+To switch back to one of the standard styles like C<concise> or
+C<terse>, use C<set_style_standard>.
+
 To see the output, call the subroutine returned by B<compile> in the
 same way that B<O> does.
 
 =head1 AUTHOR
 
-Stephen McCamant, C<smcc@CSUA.Berkeley.EDU>
+Stephen McCamant, E<lt>smcc@CSUA.Berkeley.EDUE<gt>.
 
 =cut
index 3abe615..5d568f1 100644 (file)
@@ -1,42 +1,30 @@
 package B::Terse;
 
-our $VERSION = '1.00';
+our $VERSION = '1.01';
 
 use strict;
-use B qw(peekop class walkoptree walkoptree_exec walkoptree_slow
-        main_start main_root cstring svref_2object SVf_IVisUV);
+use B qw(class);
 use B::Asmdata qw(@specialsv_name);
+use B::Concise qw(concise_cv set_style_standard);
+use Carp;
 
 sub terse {
     my ($order, $cvref) = @_;
-    my $cv = svref_2object($cvref);
+    set_style_standard("terse");
     if ($order eq "exec") {
-       walkoptree_exec($cv->START, "terse");
+       concise_cv('exec', $cvref);
     } else {
-       walkoptree_slow($cv->ROOT, "terse");
+       concise_cv('basic', $cvref);
     }
+
 }
 
 sub compile {
-    my $order = @_ ? shift : "";
-    my @options = @_;
-    B::clearsym();
-    if (@options) {
-       return sub {
-           my $objname;
-           foreach $objname (@options) {
-               $objname = "main::$objname" unless $objname =~ /::/;
-               eval "terse(\$order, \\&$objname)";
-               die "terse($order, \\&$objname) failed: $@" if $@;
-           }
-       }
-    } else {
-       if ($order eq "exec") {
-           return sub { walkoptree_exec(main_start, "terse") }
-       } else {
-           return sub { walkoptree_slow(main_root, "terse") }
-       }
-    }
+    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 {
@@ -44,102 +32,19 @@ sub indent {
     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 {
-    my ($op, $level) = @_;
-    my $targ = $op->targ;
-    $targ = ($targ > 0) ? " [$targ]" : "";
-    print indent($level), peekop($op), $targ, "\n";
+    carp "B::OP::terse is deprecated; use B::Concise instead";
+    B::Concise::b_terse(@_);
 }
 
-sub B::SVOP::terse {
-    my ($op, $level) = @_;
-    print indent($level), peekop($op), "  ";
-    $op->sv->terse(0);
-}
-
-sub B::PADOP::terse {
-    my ($op, $level) = @_;
-    print indent($level), peekop($op), "  ", $op->padix, "\n";
-}
-
-sub B::PMOP::terse {
-    my ($op, $level) = @_;
-    my $precomp = $op->precomp;
-    print indent($level), peekop($op),
-       defined($precomp) ? " /$precomp/\n" : " (regexp not compiled)\n";
-
-}
-
-sub B::PVOP::terse {
-    my ($op, $level) = @_;
-    print indent($level), peekop($op), " ", cstring($op->pv), "\n";
-}
-
-sub B::COP::terse {
-    my ($op, $level) = @_;
-    my $label = $op->label;
-    if ($label) {
-       $label = " label ".cstring($label);
-    }
-    print indent($level), peekop($op), $label || "", "\n";
-}
-
-sub B::PV::terse {
-    my ($sv, $level) = @_;
-    print indent($level);
-    printf "%s (0x%lx) %s\n", class($sv), $$sv, cstring($sv->PV);
-}
-
-sub B::AV::terse {
-    my ($sv, $level) = @_;
-    print indent($level);
-    printf "%s (0x%lx) FILL %d\n", class($sv), $$sv, $sv->FILL;
-}
-
-sub B::GV::terse {
-    my ($gv, $level) = @_;
-    my $stash = $gv->STASH->NAME;
-    if ($stash eq "main") {
-       $stash = "";
-    } else {
-       $stash = $stash . "::";
-    }
-    print indent($level);
-    printf "%s (0x%lx) *%s%s\n", class($gv), $$gv, $stash, $gv->SAFENAME;
-}
-
-sub B::IV::terse {
-    my ($sv, $level) = @_;
-    print indent($level);
-    my $v = $sv->FLAGS & SVf_IVisUV ? "%u" : "%d";
-    printf "%s (0x%lx) $v\n", class($sv), $$sv, $sv->int_value;
-}
-
-sub B::NV::terse {
-    my ($sv, $level) = @_;
-    print indent($level);
-    printf "%s (0x%lx) %s\n", class($sv), $$sv, $sv->NV;
-}
-
-sub B::RV::terse {
-    my ($rv, $level) = @_;
-    print indent($level);
-    printf "%s (0x%lx) %s\n", class($rv), $$rv, printref($rv);
-}
-
-sub printref {
-    my $rv = shift;
-    my $rcl = class($rv->RV);
-    if ($rcl eq 'PV') {
-       return "\\" . cstring($rv->RV->$rcl);
-    } elsif ($rcl eq 'NV') {
-       return "\\" . $rv->RV->$rcl;
-    } elsif ($rcl eq 'IV') {
-       return sprintf "\\%" . ($rv->RV->FLAGS & SVf_IVisUV ? "u" : "d"),
-           $rv->RV->int_value;
-    } elsif ($rcl eq 'RV') {
-       return "\\" . printref($rv->RV);
-    }
+sub B::SV::terse {
+    my($sv, $level) = (@_, 0);
+    my %info;
+    B::Concise::concise_sv($sv, \%info);
+    my $s = B::Concise::fmt_line(\%info, "#svclass~(?((#svaddr))?)~#svval", 0);
+    print indent($level), $s, "\n";
 }
 
 sub B::NULL::terse {
@@ -147,7 +52,7 @@ sub B::NULL::terse {
     print indent($level);
     printf "%s (0x%lx)\n", class($sv), $$sv;
 }
-    
+
 sub B::SPECIAL::terse {
     my ($sv, $level) = @_;
     print indent($level);
@@ -168,10 +73,25 @@ B::Terse - Walk Perl syntax tree, printing terse info about ops
 
 =head1 DESCRIPTION
 
-See F<ext/B/README>.
+This version of B::Terse is really just a wrapper that calls 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 compatiblilty 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
 
-Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
+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
index 1ad61b1..b11c873 100644 (file)
@@ -5,7 +5,7 @@ BEGIN {
        @INC = '../lib';
 }
 
-use Test::More tests => 15;
+use Test::More tests => 16;
 
 use_ok( 'B::Terse' );
 
@@ -33,7 +33,7 @@ $sub->();
 # now build some regexes that should match the dumped ops
 my ($hex, $op) = ('\(0x[a-f0-9]+\)', '\s+\w+');
 my %ops = map { $_ => qr/$_ $hex$op/ }
-       qw ( OP COP     LOOP PMOP UNOP BINOP LOGOP LISTOP );
+       qw ( OP COP LOOP PMOP UNOP BINOP LOGOP LISTOP PVOP );
 
 # split up the output lines into individual ops (terse is, well, terse!)
 # use an array here so $_ is modifiable
@@ -55,7 +55,9 @@ warn "# didn't find " . join(' ', keys %ops) if keys %ops;
 
 # XXX:
 # this tries to get at all tersified optypes in B::Terse
-# if you add AV, NULL, PADOP, PVOP, or SPECIAL, add it to the regex above too
+# if you can think of a way to produce AV, NULL, PADOP, or SPECIAL,
+# add it to the regex above too. (PADOPs are currently only produced
+# under ithreads, though).
 #
 use vars qw( $a $b );
 sub bar {
@@ -71,7 +73,7 @@ sub bar {
        # this is awful, but it gives a PMOP
        my $boo = split('', $foo);
 
-       # PMOP
+       # PVOP, LOOP
        LOOP: for (1 .. 10) {
                last LOOP if $_ % 2;
        }
@@ -83,17 +85,12 @@ sub bar {
        $foo =~ s/(a)/$1/;
 }
 
-SKIP: {
-    use Config;
-    skip("- B::Terse won't grok RVs under ithreads yet", 1)
-       if $Config{useithreads};
-    # Schwern's example of finding an RV
-    my $path = join " ", map { qq["-I$_"] } @INC;
-    $path = '-I::lib -MMac::err=unix' if $^O eq 'MacOS';
-    my $redir = $^O eq 'MacOS' ? '' : "2>&1";
-    my $items = qx{$^X $path "-MO=Terse" -le "print \\42" $redir};
-    like( $items, qr/RV $hex \\42/, 'RV' );
-}
+# Schwern's example of finding an RV
+my $path = join " ", map { qq["-I$_"] } @INC;
+$path = '-I::lib -MMac::err=unix' if $^O eq 'MacOS';
+my $redir = $^O eq 'MacOS' ? '' : "2>&1";
+my $items = qx{$^X $path "-MO=Terse" -le "print \\42" $redir};
+like( $items, qr/RV $hex \\42/, 'RV' );
 
 package TieOut;
 
index 3b41a30..c8d72e5 100644 (file)
@@ -182,10 +182,10 @@ Taking references to the elements of shared arrays and hashes does not
 autovivify the elements, and neither does slicing a shared array/hash
 over non-existent indices/keys autovivify the elements.
 
-share() allows you to C<share $hashref->{key}> without giving any error
-message.  But the C<$hashref->{key}> is B<not> shared, causing the error
+share() allows you to C<< share $hashref->{key} >> without giving any error
+message.  But the C<< $hashref->{key} >> is B<not> shared, causing the error
 "locking can only be used on shared values" to occur when you attempt to
-C<lock $hasref->{key}>.
+C<< lock $hasref->{key} >>.
 
 =head1 AUTHOR
 
index 3bbe9ea..9adcdb4 100644 (file)
@@ -52,7 +52,11 @@ archname='darwin';
 # nm works.
 usenm='true';
 
-# Optimize.
+#    Optimizing for size also mean less resident memory usage on the part
+# of Perl.  Apple asserts that this is a more important optimization than
+# saving on CPU cycles.  Given that memory speed has not increased at
+# pace with CPU speed over time (on any platform), this is probably a
+# reasonable assertion.
 if [ -z "${optimize}" ]; then
   case "$osvers" in
     [12345].*) optimize='-O3' ;;
diff --git a/op.c b/op.c
index df50baf..de5f06a 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2251,18 +2251,16 @@ Perl_scope(pTHX_ OP *o)
            o->op_type = OP_LEAVE;
            o->op_ppaddr = PL_ppaddr[OP_LEAVE];
        }
-       else {
-           if (o->op_type == OP_LINESEQ) {
-               OP *kid;
-               o->op_type = OP_SCOPE;
-               o->op_ppaddr = PL_ppaddr[OP_SCOPE];
-               kid = ((LISTOP*)o)->op_first;
-               if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)
-                   op_null(kid);
-           }
-           else
-               o = newLISTOP(OP_SCOPE, 0, o, Nullop);
+       else if (o->op_type == OP_LINESEQ) {
+           OP *kid;
+           o->op_type = OP_SCOPE;
+           o->op_ppaddr = PL_ppaddr[OP_SCOPE];
+           kid = ((LISTOP*)o)->op_first;
+           if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)
+               op_null(kid);
        }
+       else
+           o = newLISTOP(OP_SCOPE, 0, o, Nullop);
     }
     return o;
 }
@@ -2315,17 +2313,9 @@ OP*
 Perl_block_end(pTHX_ I32 floor, OP *seq)
 {
     int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
-    line_t copline = PL_copline;
     OP* retval = scalarseq(seq);
     /* If there were syntax errors, don't try to close a block */
     if (PL_yynerrs) return retval;
-    if (!seq) {
-       /* scalarseq() gave us an OP_STUB */
-       retval->op_flags |= OPf_PARENS;
-       /* there should be a nextstate in every block */
-       retval = newSTATEOP(0, Nullch, retval);
-       PL_copline = copline;  /* XXX newSTATEOP may reset PL_copline */
-    }
     LEAVE_SCOPE(floor);
     PL_pad_reset_pending = FALSE;
     PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK);
@@ -2513,19 +2503,7 @@ Perl_fold_constants(pTHX_ register OP *o)
     op_free(o);
     if (type == OP_RV2GV)
        return newGVOP(OP_GV, 0, (GV*)sv);
-    else {
-       /* try to smush double to int, but don't smush -2.0 to -2 */
-       if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK &&
-           type != OP_NEGATE)
-       {
-#ifdef PERL_PRESERVE_IVUV
-           /* Only bother to attempt to fold to IV if
-              most operators will benefit  */
-           SvIV_please(sv);
-#endif
-       }
-       return newSVOP(OP_CONST, 0, sv);
-    }
+    return newSVOP(OP_CONST, 0, sv);
 
   nope:
     return o;
index ce3b120..918f429 100644 (file)
@@ -1157,8 +1157,8 @@ only occasionally and for good reason.  Typically this might be
 done by a package attempting to emulate missing built-in functionality
 on a non-Unix system.
 
-Overriding may be done only by importing the name from a
-module--ordinary predeclaration isn't good enough.  However, the
+Overriding may be done only by importing the name from a module at
+compile time--ordinary predeclaration isn't good enough.  However, the
 C<use subs> pragma lets you, in effect, predeclare subs
 via the import syntax, and these names may then override built-in ones:
 
index 00e1e32..3f48e08 100644 (file)
@@ -1091,9 +1091,15 @@ regular expression assertion (see L<perlre>).  May be written to.
 
 =item $^S
 
-Current state of the interpreter.  Undefined if parsing of the current
-module/eval is not finished (may happen in $SIG{__DIE__} and
-$SIG{__WARN__} handlers).  True if inside an eval(), otherwise false.
+Current state of the interpreter.
+
+    $^S         State
+    ---------   -------------------
+    undef       Parsing module/eval
+    true (1)    Executing an eval
+    false (0)   Otherwise
+
+The first state may happen in $SIG{__DIE__} and $SIG{__WARN__} handlers.
 
 =item $BASETIME
 
diff --git a/pp.c b/pp.c
index 9675cc0..f450805 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -880,16 +880,15 @@ PP(pp_postdec)
 
 PP(pp_pow)
 {
-    dSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
+    dSP; dATARGET;
 #ifdef PERL_PRESERVE_IVUV
-    /* ** is implemented with pow. pow is floating point. Perl programmers
-       write 2 ** 31 and expect it to be 2147483648
-       pow never made any guarantee to deliver a result to 53 (or whatever)
-       bits of accuracy. Which is unfortunate, as perl programmers expect it
-       to, and on some platforms (eg Irix with long doubles) it doesn't in
-       a very visible case. (2 ** 31, which a regression test uses)
-       So we'll implement power-of-2 ** +ve integer with multiplies, to avoid
-       these problems.  */
+    bool is_int = 0;
+#endif
+    tryAMAGICbin(pow,opASSIGN);
+#ifdef PERL_PRESERVE_IVUV
+    /* For integer to integer power, we do the calculation by hand wherever
+       we're sure it is safe; otherwise we call pow() and try to convert to
+       integer afterwards. */
     {
         SvIV_please(TOPm1s);
         if (SvIOK(TOPm1s)) {
@@ -921,10 +920,12 @@ PP(pp_pow)
                         goto float_it; /* Can't do negative powers this way.  */
                     }
                 }
-                /* now we have integer ** positive integer.
-                   foo & (foo - 1) is zero only for a power of 2.  */
+                /* now we have integer ** positive integer. */
+                is_int = 1;
+
+                /* foo & (foo - 1) is zero only for a power of 2.  */
                 if (!(baseuv & (baseuv - 1))) {
-                    /* We are raising power-of-2 to postive integer.
+                    /* We are raising power-of-2 to a positive integer.
                        The logic here will work for any base (even non-integer
                        bases) but it can be less accurate than
                        pow (base,power) or exp (power * log (base)) when the
@@ -936,20 +937,6 @@ PP(pp_pow)
                     NV base = baseuok ? baseuv : -(NV)baseuv;
                     int n = 0;
 
-                    /* The logic is this.
-                       x ** n === x ** m1 * x ** m2 where n = m1 + m2
-                       so as 42 is 32 + 8 + 2
-                       x ** 42 can be written as
-                       x ** 32 * x ** 8 * x ** 2
-                       I can calculate x ** 2, x ** 4, x ** 8 etc trivially:
-                       x ** 2n is x ** n * x ** n
-                       So I loop round, squaring x each time
-                       (x, x ** 2, x ** 4, x ** 8) and multiply the result
-                       by the x-value whenever that bit is set in the power.
-                       To finish as soon as possible I zero bits in the power
-                       when I've done them, so that power becomes zero when
-                       I clear the last bit (no more to do), and the loop
-                       terminates.  */
                     for (; power; base *= base, n++) {
                         /* Do I look like I trust gcc with long longs here?
                            Do I hell.  */
@@ -957,24 +944,69 @@ PP(pp_pow)
                         if (power & bit) {
                             result *= base;
                             /* Only bother to clear the bit if it is set.  */
-                            power &= ~bit;
+                            power -= bit;
                            /* Avoid squaring base again if we're done. */
                            if (power == 0) break;
                         }
                     }
                     SP--;
                     SETn( result );
+                    SvIV_please(TOPs);
                     RETURN;
-                }
-            }
-        }
+               } else {
+                   register unsigned int highbit = 8 * sizeof(UV);
+                   register unsigned int lowbit = 0;
+                   register unsigned int diff;
+                   while ((diff = (highbit - lowbit) >> 1)) {
+                       if (baseuv & ~((1 << (lowbit + diff)) - 1))
+                           lowbit += diff;
+                       else 
+                           highbit -= diff;
+                   }
+                   /* we now have baseuv < 2 ** highbit */
+                   if (power * highbit <= 8 * sizeof(UV)) {
+                       /* result will definitely fit in UV, so use UV math
+                          on same algorithm as above */
+                       register UV result = 1;
+                       register UV base = baseuv;
+                       register int n = 0;
+                       for (; power; base *= base, n++) {
+                           register UV bit = (UV)1 << (UV)n;
+                           if (power & bit) {
+                               result *= base;
+                               power -= bit;
+                               if (power == 0) break;
+                           }
+                       }
+                       SP--;
+                       if (baseuok || !(power & 1))
+                           /* answer is positive */
+                           SETu( result );
+                       else if (result <= (UV)IV_MAX)
+                           /* answer negative, fits in IV */
+                           SETi( -(IV)result );
+                       else if (result == (UV)IV_MIN) 
+                           /* 2's complement assumption: special case IV_MIN */
+                           SETi( IV_MIN );
+                       else
+                           /* answer negative, doesn't fit */
+                           SETn( -(NV)result );
+                       RETURN;
+                   } 
+               }
+           }
+       }
     }
-      float_it:
+  float_it:
 #endif    
     {
-        dPOPTOPnnrl;
-        SETn( Perl_pow( left, right) );
-        RETURN;
+       dPOPTOPnnrl;
+       SETn( Perl_pow( left, right) );
+#ifdef PERL_PRESERVE_IVUV
+       if (is_int)
+           SvIV_please(TOPs);
+#endif
+       RETURN;
     }
 }
 
@@ -3095,6 +3127,8 @@ PP(pp_substr)
                    sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
            }
 
+           if (SvREFCNT(TARG) > 1)     /* don't share the TARG (#20933) */
+               TARG = sv_newmortal();
            if (SvTYPE(TARG) < SVt_PVLV) {
                sv_upgrade(TARG, SVt_PVLV);
                sv_magic(TARG, Nullsv, PERL_MAGIC_substr, Nullch, 0);
@@ -3125,6 +3159,8 @@ PP(pp_vec)
 
     SvTAINTED_off(TARG);               /* decontaminate */
     if (lvalue) {                      /* it's an lvalue! */
+       if (SvREFCNT(TARG) > 1) /* don't share the TARG (#20933) */
+           TARG = sv_newmortal();
        if (SvTYPE(TARG) < SVt_PVLV) {
            sv_upgrade(TARG, SVt_PVLV);
            sv_magic(TARG, Nullsv, PERL_MAGIC_vec, Nullch, 0);
@@ -4448,6 +4484,7 @@ PP(pp_split)
            }
            /* temporarily switch stacks */
            SWITCHSTACK(PL_curstack, ary);
+           PL_curstackinfo->si_stack = ary;
            make_mortal = 0;
        }
     }
@@ -4645,6 +4682,7 @@ PP(pp_split)
     if (realarray) {
        if (!mg) {
            SWITCHSTACK(ary, oldstack);
+           PL_curstackinfo->si_stack = oldstack;
            if (SvSMAGICAL(ary)) {
                PUTBACK;
                mg_set((SV*)ary);
index 9f12e0e..8b80471 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1989,6 +1989,7 @@ S_dofindlabel(pTHX_ OP *o, char *label, OP **opstack, OP **oplimit)
     if (o->op_type == OP_LEAVE ||
        o->op_type == OP_SCOPE ||
        o->op_type == OP_LEAVELOOP ||
+       o->op_type == OP_LEAVESUB ||
        o->op_type == OP_LEAVETRY)
     {
        *ops++ = cUNOPo->op_first;
@@ -2315,6 +2316,7 @@ PP(pp_goto)
     if (label && *label) {
        OP *gotoprobe = 0;
        bool leaving_eval = FALSE;
+       bool in_block = FALSE;
         PERL_CONTEXT *last_eval_cx = 0;
 
        /* find label */
@@ -2340,9 +2342,10 @@ PP(pp_goto)
            case CXt_SUBST:
                continue;
            case CXt_BLOCK:
-               if (ix)
+               if (ix) {
                    gotoprobe = cx->blk_oldcop->op_sibling;
-               else
+                   in_block = TRUE;
+               } else
                    gotoprobe = PL_main_root;
                break;
            case CXt_SUB:
@@ -2399,7 +2402,8 @@ PP(pp_goto)
 
        if (*enterops && enterops[1]) {
            OP *oldop = PL_op;
-           for (ix = 1; enterops[ix]; ix++) {
+           ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1;
+           for (; enterops[ix]; ix++) {
                PL_op = enterops[ix];
                /* Eventually we may want to stack the needed arguments
                 * for each op.  For now, we punt on the hard ones. */
index a0b4d55..122c624 100755 (executable)
@@ -2,7 +2,7 @@
 
 # "This IS structured code.  It's just randomly structured."
 
-print "1..22\n";
+print "1..27\n";
 
 while ($?) {
     $foo = 1;
@@ -144,6 +144,39 @@ $ok = 0 if $@;
 }
 print ($ok ? "ok 22\n" : "not ok 22\n");
 
+{
+    my $false = 0;
+
+    $ok = 0;
+    { goto A; A: $ok = 1 } continue { }
+    print "not " unless $ok;
+    print "ok 23 - #20357 goto inside /{ } continue { }/ loop\n";
+
+    $ok = 0;
+    { do { goto A; A: $ok = 1 } while $false }
+    print "not " unless $ok;
+    print "ok 24 - #20154 goto inside /do { } while ()/ loop\n";
+
+    $ok = 0;
+    foreach(1) { goto A; A: $ok = 1 } continue { };
+    print "not " unless $ok;
+    print "ok 25 - goto inside /foreach () { } continue { }/ loop\n";
+
+    $ok = 0;
+    sub a {
+       A: { if ($false) { redo A; B: $ok = 1; redo A; } }
+       goto B unless $r++
+    }
+    a();
+    print "not " unless $ok;
+    print "ok 26 - #19061 loop label wiped away by goto\n";
+
+    $ok = 0;
+    for ($p=1;$p && goto A;$p=0) { A: $ok = 1 }
+    print "not " unless $ok;
+    print "ok 27 - weird case of goto and for(;;) loop\n";
+}
+
 exit;
 
 bypass:
index 9f02257..243b0c7 100644 (file)
--- a/t/op/lc.t
+++ b/t/op/lc.t
@@ -128,16 +128,16 @@ $a = "\x{3c3}foo.bar"; # \x{3c3} == GREEK SMALL LETTER SIGMA.
 $b = "\x{3a3}FOO.BAR"; # \x{3a3} == GREEK CAPITAL LETTER SIGMA.
 
 ($c = $b) =~ s/(\w+)/lc($1)/ge;
-ok($c eq $a, "Using s///e to change case.");
+is($c , $a, "Using s///e to change case.");
 
 ($c = $a) =~ s/(\w+)/uc($1)/ge;
-ok($c eq $b, "Using s///e to change case.");
+is($c , $b, "Using s///e to change case.");
 
 ($c = $b) =~ s/(\w+)/lcfirst($1)/ge;
-ok($c eq "\x{3c3}FOO.bAR", "Using s///e to change case.");
+is($c , "\x{3c3}FOO.bAR", "Using s///e to change case.");
 
 ($c = $a) =~ s/(\w+)/ucfirst($1)/ge;
-ok($c eq "\x{3a3}foo.Bar", "Using s///e to change case.");
+is($c , "\x{3a3}foo.Bar", "Using s///e to change case.");
 
 # #18931: perl5.8.0 bug in \U..\E processing
 # Test case from Nick Clark.
@@ -158,4 +158,3 @@ for my $a (0,1) {
        $test++;
     } 
 }
-
index fb3d565..3d7e898 100755 (executable)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 51;
+plan tests => 50;
 
 $FS = ':';
 
@@ -265,13 +265,21 @@ ok(@ary == 3 &&
 
 {
     # [perl #18195]
-    for my $u (0, 1) {
-       for my $a (0, 1) {
-           $_ = 'readin,database,readout';
-           utf8::upgrade $_ if $u;
-           /(.+)/;
-           my @d = split /[,]/,$1;
-           is(join (':',@d), 'readin:database:readout', "[perl #18195]");
+    for my $a (0,1) {
+       $_ = 'readin,database,readout';
+       if ($ARGV[0])  {
+           $_ .= chr 256;
+           chop;
        }
+       /(.+)/;
+       my @d = split /[,]/,$1;
+       is(join (':',@d), 'readin:database:readout', "[perl #18195]")
     }
 }
+
+{
+    $p="a,b";
+    utf8::upgrade $p;
+    @a=split(/[, ]+/,$p);
+    is ("$@-@a-", '-a b-', '#20912 - split() to array with /[]+/ and utf8');
+}
index 85574d5..17f86e3 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..174\n";
+print "1..175\n";
 
 #P = start of string  Q = start of substr  R = end of substr  S = end of string
 
@@ -585,3 +585,10 @@ ok 173, $x eq "\xFFb\x{100}\x{200}";
 substr($x = "\x{100}\x{200}", 2, 0, "\xFFb");
 ok 174, $x eq "\x{100}\x{200}\xFFb";
 
+# [perl #20933]
+{ 
+    my $s = "ab";
+    my @r; 
+    $r[$_] = \ substr $s, $_, 1 for (0, 1);
+    ok 175, join("", map { $$_ } @r) eq "ab";
+}
index 67d7527..158711f 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..30\n";
+print "1..31\n";
 
 my $Is_EBCDIC = (ord('A') == 193) ? 1 : 0;
 
@@ -86,3 +86,14 @@ print "ok 29\n";
 vec(substr($foo, 1,3), 5, 4) = 3;
 print "not " if $foo ne "\x61\x62\x63\x34\x65\x66";
 print "ok 30\n";
+
+# A variation of [perl #20933]
+{
+    my $s = "";
+    vec($s, 0, 1) = 0;
+    vec($s, 1, 1) = 1;
+    my @r;
+    $r[$_] = \ vec $s, $_, 1 for (0, 1);
+    print "not " if (${ $r[0] } != 0 || ${ $r[1] } != 1);
+    print "ok 31\n";
+}
index 27880dd..a975608 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -4479,15 +4479,19 @@ vms_image_init(int *argcp, char ***argvp)
    * hasn't been allocated when vms_image_init() is called.
    */
   if (will_taint) {
-    char ***newap;
-    New(1320,newap,*argcp+2,char **);
-    newap[0] = argvp[0];
-    *newap[1] = "-T";
-    Copy(argvp[1],newap[2],*argcp-1,char **);
+    char **newargv, **oldargv;
+    oldargv = *argvp;
+    New(1320,newargv,(*argcp)+2,char *);
+    newargv[0] = oldargv[0];
+    New(1320,newargv[1],3,char);
+    strcpy(newargv[1], "-T");
+    Copy(&oldargv[1],&newargv[2],(*argcp)-1,char **);
+    (*argcp)++;
+    newargv[*argcp] = NULL;
     /* We orphan the old argv, since we don't know where it's come from,
      * so we don't know how to free it.
      */
-    *argcp++; argvp = newap;
+    *argvp = newargv;
   }
   else {  /* Did user explicitly request tainting? */
     int i;