This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Too many 64-bitness option combinations.
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 7824c22..ed5a7eb 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1,6 +1,6 @@
 /*    op.c
  *
- *    Copyright (c) 1991-1999, Larry Wall
+ *    Copyright (c) 1991-2000, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 /* #define PL_OP_SLAB_ALLOC */
 
 /* XXXXXX testing */
-#define OP_REFCNT_LOCK         NOOP
-#define OP_REFCNT_UNLOCK       NOOP
-#define OpREFCNT_set(o,n)      NOOP
-#define OpREFCNT_dec(o)                ((o)->op_targ--)
+#ifdef USE_ITHREADS
+#  define OP_REFCNT_LOCK               NOOP
+#  define OP_REFCNT_UNLOCK             NOOP
+#  define OpREFCNT_set(o,n)            ((o)->op_targ = (n))
+#  define OpREFCNT_dec(o)              (--(o)->op_targ)
+#else
+#  define OP_REFCNT_LOCK               NOOP
+#  define OP_REFCNT_UNLOCK             NOOP
+#  define OpREFCNT_set(o,n)            NOOP
+#  define OpREFCNT_dec(o)              0
+#endif
 
 #ifdef PL_OP_SLAB_ALLOC 
 #define SLAB_SIZE 8192
@@ -144,22 +151,43 @@ Perl_pad_allocmy(pTHX_ char *name)
        }
        yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
     }
-    if (ckWARN(WARN_UNSAFE) && AvFILLp(PL_comppad_name) >= 0) {
+    if (ckWARN(WARN_MISC) && AvFILLp(PL_comppad_name) >= 0) {
        SV **svp = AvARRAY(PL_comppad_name);
-       for (off = AvFILLp(PL_comppad_name); off > PL_comppad_name_floor; off--) {
+       HV *ourstash = (PL_curstash ? PL_curstash : PL_defstash);
+       PADOFFSET top = AvFILLp(PL_comppad_name);
+       for (off = top; off > PL_comppad_name_floor; off--) {
            if ((sv = svp[off])
                && sv != &PL_sv_undef
                && (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
+               && (PL_in_my != KEY_our
+                   || ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash))
                && strEQ(name, SvPVX(sv)))
            {
-               Perl_warner(aTHX_ WARN_UNSAFE,
-                       "\"%s\" variable %s masks earlier declaration in same %s", 
-                       (PL_in_my == KEY_our ? "our" : "my"),
-                       name,
-                       (SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
+               Perl_warner(aTHX_ WARN_MISC,
+                   "\"%s\" variable %s masks earlier declaration in same %s", 
+                   (PL_in_my == KEY_our ? "our" : "my"),
+                   name,
+                   (SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
+               --off;
                break;
            }
        }
+       if (PL_in_my == KEY_our) {
+           while (off >= 0 && off <= top) {
+               if ((sv = svp[off])
+                   && sv != &PL_sv_undef
+                   && ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash)
+                   && strEQ(name, SvPVX(sv)))
+               {
+                   Perl_warner(aTHX_ WARN_MISC,
+                       "\"our\" variable %s redeclared", name);
+                   Perl_warner(aTHX_ WARN_MISC,
+                       "(Did you mean \"local\" instead of \"our\"?)\n");
+                   break;
+               }
+               --off;
+           }
+       }
     }
     off = pad_alloc(OP_PADSV, SVs_PADMY);
     sv = NEWSV(1102,0);
@@ -167,15 +195,18 @@ Perl_pad_allocmy(pTHX_ char *name)
     sv_setpv(sv, name);
     if (PL_in_my_stash) {
        if (*name != '$')
-           yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"my\"",
-                        name));
+           yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"",
+                        name, PL_in_my == KEY_our ? "our" : "my"));
        SvOBJECT_on(sv);
        (void)SvUPGRADE(sv, SVt_PVMG);
        SvSTASH(sv) = (HV*)SvREFCNT_inc(PL_in_my_stash);
        PL_sv_objcount++;
     }
-    if (PL_in_my == KEY_our)
+    if (PL_in_my == KEY_our) {
+       (void)SvUPGRADE(sv, SVt_PVGV);
+       GvSTASH(sv) = (HV*)SvREFCNT_inc(PL_curstash ? (SV*)PL_curstash : (SV*)PL_defstash);
        SvFLAGS(sv) |= SVpad_OUR;
+    }
     av_store(PL_comppad_name, off, sv);
     SvNVX(sv) = (NV)PAD_MAX;
     SvIVX(sv) = 0;                     /* Not yet introduced--see newSTATEOP */
@@ -190,6 +221,31 @@ Perl_pad_allocmy(pTHX_ char *name)
     return off;
 }
 
+STATIC PADOFFSET
+S_pad_addlex(pTHX_ SV *proto_namesv)
+{
+    SV *namesv = NEWSV(1103,0);
+    PADOFFSET newoff = pad_alloc(OP_PADSV, SVs_PADMY);
+    sv_upgrade(namesv, SVt_PVNV);
+    sv_setpv(namesv, SvPVX(proto_namesv));
+    av_store(PL_comppad_name, newoff, namesv);
+    SvNVX(namesv) = (NV)PL_curcop->cop_seq;
+    SvIVX(namesv) = PAD_MAX;                   /* A ref, intro immediately */
+    SvFAKE_on(namesv);                         /* A ref, not a real var */
+    if (SvFLAGS(proto_namesv) & SVpad_OUR) {   /* An "our" variable */
+       SvFLAGS(namesv) |= SVpad_OUR;
+       (void)SvUPGRADE(namesv, SVt_PVGV);
+       GvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)GvSTASH(proto_namesv));
+    }
+    if (SvOBJECT(proto_namesv)) {              /* A typed var */
+       SvOBJECT_on(namesv);
+       (void)SvUPGRADE(namesv, SVt_PVMG);
+       SvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)SvSTASH(proto_namesv));
+       PL_sv_objcount++;
+    }
+    return newoff;
+}
+
 #define FINDLEX_NOSEARCH       1               /* don't search outer contexts */
 
 STATIC PADOFFSET
@@ -232,25 +288,10 @@ S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv,
                    }
                    depth = 1;
                }
-               oldpad = (AV*)*av_fetch(curlist, depth, FALSE);
+               oldpad = (AV*)AvARRAY(curlist)[depth];
                oldsv = *av_fetch(oldpad, off, TRUE);
                if (!newoff) {          /* Not a mere clone operation. */
-                   SV *namesv = NEWSV(1103,0);
-                   newoff = pad_alloc(OP_PADSV, SVs_PADMY);
-                   sv_upgrade(namesv, SVt_PVNV);
-                   sv_setpv(namesv, name);
-                   av_store(PL_comppad_name, newoff, namesv);
-                   SvNVX(namesv) = (NV)PL_curcop->cop_seq;
-                   SvIVX(namesv) = PAD_MAX;    /* A ref, intro immediately */
-                   SvFAKE_on(namesv);          /* A ref, not a real var */
-                   if (SvFLAGS(sv) & SVpad_OUR)/* An "our" variable */
-                       SvFLAGS(namesv) |= SVpad_OUR;
-                   if (SvOBJECT(sv)) {         /* A typed var */
-                       SvOBJECT_on(namesv);
-                       (void)SvUPGRADE(namesv, SVt_PVMG);
-                       SvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)SvSTASH(sv));
-                       PL_sv_objcount++;
-                   }
+                   newoff = pad_addlex(sv);
                    if (CvANON(PL_compcv) || SvTYPE(PL_compcv) == SVt_PVFM) {
                        /* "It's closures all the way down." */
                        CvCLONE_on(PL_compcv);
@@ -264,8 +305,23 @@ S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv,
                                 bcv && bcv != cv && !CvCLONE(bcv);
                                 bcv = CvOUTSIDE(bcv))
                            {
-                               if (CvANON(bcv))
+                               if (CvANON(bcv)) {
+                                   /* install the missing pad entry in intervening
+                                    * nested subs and mark them cloneable.
+                                    * XXX fix pad_foo() to not use globals */
+                                   AV *ocomppad_name = PL_comppad_name;
+                                   AV *ocomppad = PL_comppad;
+                                   SV **ocurpad = PL_curpad;
+                                   AV *padlist = CvPADLIST(bcv);
+                                   PL_comppad_name = (AV*)AvARRAY(padlist)[0];
+                                   PL_comppad = (AV*)AvARRAY(padlist)[1];
+                                   PL_curpad = AvARRAY(PL_comppad);
+                                   pad_addlex(sv);
+                                   PL_comppad_name = ocomppad_name;
+                                   PL_comppad = ocomppad;
+                                   PL_curpad = ocurpad;
                                    CvCLONE_on(bcv);
+                               }
                                else {
                                    if (ckWARN(WARN_CLOSURE)
                                        && !CvUNIQUE(bcv) && !CvUNIQUE(cv))
@@ -505,8 +561,12 @@ Perl_pad_free(pTHX_ PADOFFSET po)
     DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%"UVxf" free %"IVdf"\n",
                          PTR2UV(PL_curpad), (IV)po));
 #endif /* USE_THREADS */
-    if (PL_curpad[po] && PL_curpad[po] != &PL_sv_undef)
+    if (PL_curpad[po] && PL_curpad[po] != &PL_sv_undef) {
        SvPADTMP_off(PL_curpad[po]);
+#ifdef USE_ITHREADS
+       SvREADONLY_off(PL_curpad[po]);  /* could be a freed constant */
+#endif
+    }
     if ((I32)po < PL_padix)
        PL_padix = po - 1;
 }
@@ -660,7 +720,6 @@ Perl_op_free(pTHX_ OP *o)
                OP_REFCNT_UNLOCK;
                return;
            }
-           o->op_targ = 0;             /* XXXXXX */
            OP_REFCNT_UNLOCK;
            break;
        default:
@@ -722,7 +781,7 @@ S_op_clear(pTHX_ OP *o)
 #ifdef USE_ITHREADS
        if (cPADOPo->op_padix > 0) {
            if (PL_curpad) {
-               GV *gv = cGVOPo;
+               GV *gv = cGVOPo_gv;
                pad_swipe(cPADOPo->op_padix);
                /* No GvIN_PAD_off(gv) here, because other references may still
                 * exist on the pad */
@@ -1056,7 +1115,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_GGRGID:
     case OP_GETLOGIN:
       func_ops:
-       if (!(o->op_private & OPpLVAL_INTRO))
+       if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)))
            useless = PL_op_desc[o->op_type];
        break;
 
@@ -1064,7 +1123,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_RV2SV:
     case OP_RV2AV:
     case OP_RV2HV:
-       if (!(o->op_private & OPpLVAL_INTRO) &&
+       if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)) &&
                (!o->op_sibling || o->op_sibling->op_type != OP_READLINE))
            useless = "a variable";
        break;
@@ -1353,18 +1412,19 @@ Perl_mod(pTHX_ OP *o, I32 type)
                    if (kid->op_type == OP_METHOD_NAMED
                        || kid->op_type == OP_METHOD)
                    {
-                       OP *newop;
+                       UNOP *newop;
 
                        if (kid->op_sibling || kid->op_next != kid) {
                            yyerror("panic: unexpected optree near method call");
                            break;
                        }
                        
-                       NewOp(1101, newop, 1, OP);
+                       NewOp(1101, newop, 1, UNOP);
                        newop->op_type = OP_RV2CV;
                        newop->op_ppaddr = PL_ppaddr[OP_RV2CV];
-                       newop->op_next = newop;
-                       kid->op_sibling = newop;
+                       newop->op_first = Nullop;
+                        newop->op_next = (OP*)newop;
+                       kid->op_sibling = (OP*)newop;
                        newop->op_private |= OPpLVAL_INTRO;
                        break;
                    }
@@ -1403,7 +1463,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
                    break;
                }
                
-               cv = GvCV(kGVOP);
+               cv = GvCV(kGVOP_gv);
                if (!cv) 
                    goto restore_2cv;
                if (CvLVALUE(cv))
@@ -1671,7 +1731,7 @@ Perl_ref(pTHX_ OP *o, I32 type)
 
     switch (o->op_type) {
     case OP_ENTERSUB:
-       if ((type == OP_DEFINED || type == OP_LOCK) &&
+       if ((type == OP_EXISTS || type == OP_DEFINED || type == OP_LOCK) &&
            !(o->op_flags & OPf_STACKED)) {
            o->op_type = OP_RV2CV;             /* entersub => rv2cv */
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
@@ -1820,13 +1880,16 @@ S_my_kid(pTHX_ OP *o, OP *attrs)
     } else if (type == OP_RV2SV ||     /* "our" declaration */
               type == OP_RV2AV ||
               type == OP_RV2HV) { /* XXX does this let anything illegal in? */
+       o->op_private |= OPpOUR_INTRO;
        return o;
     } else if (type != OP_PADSV &&
             type != OP_PADAV &&
             type != OP_PADHV &&
             type != OP_PUSHMARK)
     {
-       yyerror(Perl_form(aTHX_ "Can't declare %s in my", PL_op_desc[o->op_type]));
+       yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
+                         PL_op_desc[o->op_type],
+                         PL_in_my == KEY_our ? "our" : "my"));
        return o;
     }
     else if (attrs && type != OP_PUSHMARK) {
@@ -1834,6 +1897,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs)
        SV *padsv;
        SV **namesvp;
 
+       PL_in_my = FALSE;
+       PL_in_my_stash = Nullhv;
+
        /* check for C<my Dog $spot> when deciding package */
        namesvp = av_fetch(PL_comppad_name, o->op_targ, FALSE);
        if (namesvp && *namesvp && SvOBJECT(*namesvp) && HvNAME(SvSTASH(*namesvp)))
@@ -1853,11 +1919,12 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
 {
     if (o->op_flags & OPf_PARENS)
        list(o);
-    PL_in_my = FALSE;
-    PL_in_my_stash = Nullhv;
     if (attrs)
        SAVEFREEOP(attrs);
-    return my_kid(o, attrs);
+    o = my_kid(o, attrs);
+    PL_in_my = FALSE;
+    PL_in_my_stash = Nullhv;
+    return o;
 }
 
 OP *
@@ -1880,7 +1947,7 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
     dTHR;
     OP *o;
 
-    if (ckWARN(WARN_UNSAFE) &&
+    if (ckWARN(WARN_MISC) &&
       (left->op_type == OP_RV2AV ||
        left->op_type == OP_RV2HV ||
        left->op_type == OP_PADAV ||
@@ -1891,7 +1958,7 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
       const char *sample = ((left->op_type == OP_RV2AV ||
                             left->op_type == OP_PADAV)
                            ? "@array" : "%hash");
-      Perl_warner(aTHX_ WARN_UNSAFE,
+      Perl_warner(aTHX_ WARN_MISC,
              "Applying %s to %s will act on scalar(%s)", 
              desc, sample, sample);
     }
@@ -1965,12 +2032,11 @@ Perl_block_start(pTHX_ int full)
     int retval = PL_savestack_ix;
 
     SAVEI32(PL_comppad_name_floor);
-    if (full) {
-       if ((PL_comppad_name_fill = AvFILLp(PL_comppad_name)) > 0)
-           PL_comppad_name_floor = PL_comppad_name_fill;
-       else
-           PL_comppad_name_floor = 0;
-    }
+    PL_comppad_name_floor = AvFILLp(PL_comppad_name);
+    if (full)
+       PL_comppad_name_fill = PL_comppad_name_floor;
+    if (PL_comppad_name_floor < 0)
+       PL_comppad_name_floor = 0;
     SAVEI32(PL_min_intro_pending);
     SAVEI32(PL_max_intro_pending);
     PL_min_intro_pending = 0;
@@ -1985,8 +2051,6 @@ Perl_block_start(pTHX_ int full)
         PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
         SAVEFREESV(PL_compiling.cop_warnings) ;
     }
-
-
     return retval;
 }
 
@@ -2071,16 +2135,18 @@ Perl_localize(pTHX_ OP *o, I32 lex)
            char *s;
            for (s = PL_bufptr; *s && (isALNUM(*s) || (*s & 0x80) || strchr("@$%, ",*s)); s++) ;
            if (*s == ';' || *s == '=')
-               Perl_warner(aTHX_ WARN_PARENTHESIS, "Parentheses missing around \"%s\" list",
-                               lex ? "my" : "local");
+               Perl_warner(aTHX_ WARN_PARENTHESIS,
+                           "Parentheses missing around \"%s\" list",
+                           lex ? (PL_in_my == KEY_our ? "our" : "my") : "local");
        }
     }
-    PL_in_my = FALSE;
-    PL_in_my_stash = Nullhv;
     if (lex)
-       return my(o);
+       o = my(o);
     else
-       return mod(o, OP_NULL);         /* a bit kludgey */
+       o = mod(o, OP_NULL);            /* a bit kludgey */
+    PL_in_my = FALSE;
+    PL_in_my_stash = Nullhv;
+    return o;
 }
 
 OP *
@@ -2230,6 +2296,7 @@ Perl_gen_constant_list(pTHX_ register OP *o)
 
     PL_op = curop = LINKLIST(o);
     o->op_next = 0;
+    peep(curop);
     pp_pushmark();
     CALLRUNOPS(aTHX);
     PL_op = curop;
@@ -2540,7 +2607,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        I32 to_utf      = o->op_private & OPpTRANS_TO_UTF;
 
        if (complement) {
-           U8 tmpbuf[10];
+           U8 tmpbuf[UTF8_MAXLEN];
            U8** cp;
            UV nextmin = 0;
            New(1109, cp, tlen, U8*);
@@ -2642,15 +2709,19 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            if (rfirst == 0xffffffff) {
                diff = tdiff;   /* oops, pretend rdiff is infinite */
                if (diff > 0)
-                   Perl_sv_catpvf(aTHX_ listsv, "%04x\t%04x\tXXXX\n", tfirst, tlast);
+                   Perl_sv_catpvf(aTHX_ listsv, "%04lx\t%04lx\tXXXX\n",
+                                  (long)tfirst, (long)tlast);
                else
-                   Perl_sv_catpvf(aTHX_ listsv, "%04x\t\tXXXX\n", tfirst);
+                   Perl_sv_catpvf(aTHX_ listsv, "%04lx\t\tXXXX\n", (long)tfirst);
            }
            else {
                if (diff > 0)
-                   Perl_sv_catpvf(aTHX_ listsv, "%04x\t%04x\t%04x\n", tfirst, tfirst + diff, rfirst);
+                   Perl_sv_catpvf(aTHX_ listsv, "%04lx\t%04lx\t%04lx\n",
+                                  (long)tfirst, (long)(tfirst + diff),
+                                  (long)rfirst);
                else
-                   Perl_sv_catpvf(aTHX_ listsv, "%04x\t\t%04x\n", tfirst, rfirst);
+                   Perl_sv_catpvf(aTHX_ listsv, "%04lx\t\t%04lx\n",
+                                  (long)tfirst, (long)rfirst);
 
                if (rfirst + diff > max)
                    max = rfirst + diff;
@@ -2797,12 +2868,16 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
            p = SvPV(pat, plen);
            pm->op_pmflags |= PMf_SKIPWHITE;
        }
+       if ((PL_hints & HINT_UTF8) || (SvUTF8(pat) && !(PL_hints & HINT_BYTE)))
+           pm->op_pmdynflags |= PMdf_UTF8;
        pm->op_pmregexp = CALLREGCOMP(aTHX_ p, p + plen, pm);
        if (strEQ("\\s+", pm->op_pmregexp->precomp))
            pm->op_pmflags |= PMf_WHITE;
        op_free(expr);
     }
     else {
+       if (PL_hints & HINT_UTF8)
+           pm->op_pmdynflags |= PMdf_UTF8;
        if (pm->op_pmflags & PMf_KEEP || !(PL_hints & HINT_RE_EVAL))
            expr = newUNOP((!(PL_hints & HINT_RE_EVAL) 
                            ? OP_REGCRESET
@@ -2861,7 +2936,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
                    }
 #else
                    if (curop->op_type == OP_GV) {
-                       GV *gv = cGVOPx(curop);
+                       GV *gv = cGVOPx_gv(curop);
                        repl_has_vars = 1;
                        if (strchr("&`'123456789+", *GvENAME(gv)))
                            break;
@@ -3031,45 +3106,55 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg)
 
     veop = Nullop;
 
-    if(version != Nullop) {
+    if (version != Nullop) {
        SV *vesv = ((SVOP*)version)->op_sv;
 
-       if (arg == Nullop && !SvNIOK(vesv)) {
+       if (arg == Nullop && !SvNIOKp(vesv)) {
            arg = version;
        }
        else {
            OP *pack;
+           SV *meth;
 
-           if (version->op_type != OP_CONST || !SvNIOK(vesv))
+           if (version->op_type != OP_CONST || !SvNIOKp(vesv))
                Perl_croak(aTHX_ "Version number must be constant number");
 
            /* Make copy of id so we don't free it twice */
            pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv));
 
            /* Fake up a method call to VERSION */
+           meth = newSVpvn("VERSION",7);
+           sv_upgrade(meth, SVt_PVIV);
+           SvIOK_on(meth);
+           PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
            veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
                            append_elem(OP_LIST,
-                           prepend_elem(OP_LIST, pack, list(version)),
-                           newSVOP(OP_METHOD_NAMED, 0,
-                                   newSVpvn("VERSION", 7))));
+                                       prepend_elem(OP_LIST, pack, list(version)),
+                                       newSVOP(OP_METHOD_NAMED, 0, meth)));
        }
     }
 
     /* Fake up an import/unimport */
     if (arg && arg->op_type == OP_STUB)
        imop = arg;             /* no import on explicit () */
-    else if(SvNIOK(((SVOP*)id)->op_sv)) {
+    else if (SvNIOKp(((SVOP*)id)->op_sv)) {
        imop = Nullop;          /* use 5.0; */
     }
     else {
+       SV *meth;
+
        /* Make copy of id so we don't free it twice */
        pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv));
+
+       /* Fake up a method call to import/unimport */
+       meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);;
+       sv_upgrade(meth, SVt_PVIV);
+       SvIOK_on(meth);
+       PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
        imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
-                   append_elem(OP_LIST,
-                       prepend_elem(OP_LIST, pack, list(arg)),
-                       newSVOP(OP_METHOD_NAMED, 0,
-                               aver ? newSVpvn("import", 6)
-                                    : newSVpvn("unimport", 8))));
+                      append_elem(OP_LIST,
+                                  prepend_elem(OP_LIST, pack, list(arg)),
+                                  newSVOP(OP_METHOD_NAMED, 0, meth)));
     }
 
     /* Fake up a require, handle override, if any */
@@ -3209,7 +3294,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
            for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
                if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
                    if (curop->op_type == OP_GV) {
-                       GV *gv = cGVOPx(curop);
+                       GV *gv = cGVOPx_gv(curop);
                        if (gv == PL_defgv || SvCUR(gv) == PL_generation)
                            break;
                        SvCUR(gv) = PL_generation;
@@ -3329,7 +3414,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
        cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ];
     }
     cop->op_flags = flags;
-    cop->op_private = (PL_hints & HINT_UTF8);
+    cop->op_private = (PL_hints & HINT_BYTE);
 #ifdef NATIVE_HINTS
     cop->op_private |= NATIVE_HINTS;
 #endif
@@ -3365,7 +3450,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
        SV **svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE);
        if (svp && *svp != &PL_sv_undef && !SvIOK(*svp)) {
            (void)SvIOK_on(*svp);
-           SvIVX(*svp) = (IV)cop;
+           SvIVX(*svp) = PTR2IV(cop);
        }
     }
 
@@ -3430,9 +3515,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
        }
     }
     if (first->op_type == OP_CONST) {
-       if (ckWARN(WARN_PRECEDENCE) && (first->op_private & OPpCONST_BARE))
-           Perl_warner(aTHX_ WARN_PRECEDENCE, "Probable precedence problem on %s", 
-                       PL_op_desc[type]);
+       if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE))
+           Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional"); 
        if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
            op_free(first);
            *firstp = Nullop;
@@ -3450,7 +3534,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
        else
            scalar(other);
     }
-    else if (ckWARN(WARN_UNSAFE) && (first->op_flags & OPf_KIDS)) {
+    else if (ckWARN(WARN_MISC) && (first->op_flags & OPf_KIDS)) {
        OP *k1 = ((UNOP*)first)->op_first;
        OP *k2 = k1->op_sibling;
        OPCODE warnop = 0;
@@ -3479,7 +3563,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
        if (warnop) {
            line_t oldline = CopLINE(PL_curcop);
            CopLINE_set(PL_curcop, PL_copline);
-           Perl_warner(aTHX_ WARN_UNSAFE,
+           Perl_warner(aTHX_ WARN_MISC,
                 "Value of %s%s can be \"0\"; test with defined()",
                 PL_op_desc[warnop],
                 ((warnop == OP_READLINE || warnop == OP_GLOB)
@@ -3680,6 +3764,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
     OP *listop;
     OP *o;
     OP *condop;
+    U8 loopflags = 0;
 
     if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
                 || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
@@ -3708,9 +3793,14 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
 
     if (!block)
        block = newOP(OP_NULL, 0);
+    else if (cont) {
+       block = scope(block);
+    }
 
-    if (cont)
+    if (cont) {
        next = LINKLIST(cont);
+       loopflags |= OPpLOOP_CONTINUE;
+    }
     if (expr) {
        cont = append_elem(OP_LINESEQ, cont, newOP(OP_UNSTACK, 0));
        if ((line_t)whileline != NOLINE) {
@@ -3753,6 +3843,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
 
     loop->op_redoop = redo;
     loop->op_lastop = o;
+    o->op_private |= loopflags;
 
     if (next)
        loop->op_nextop = next;
@@ -3979,7 +4070,7 @@ S_cv_dump(pTHX_ CV *cv)
        if (SvPOK(pname[ix]))
            PerlIO_printf(Perl_debug_log,
                          "\t%4d. 0x%"UVxf" (%s\"%s\" %"IVdf"-%"IVdf")\n",
-                         ix, PTR2UV(ppad[ix]),
+                         (int)ix, PTR2UV(ppad[ix]),
                          SvFAKE(pname[ix]) ? "FAKE " : "",
                          SvPVX(pname[ix]),
                          (IV)I_32(SvNVX(pname[ix])),
@@ -4007,8 +4098,7 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside)
     assert(!CvUNIQUE(proto));
 
     ENTER;
-    SAVEVPTR(PL_curpad);
-    SAVESPTR(PL_comppad);
+    SAVECOMPPAD();
     SAVESPTR(PL_comppad_name);
     SAVESPTR(PL_compcv);
 
@@ -4127,9 +4217,9 @@ CV *
 Perl_cv_clone(pTHX_ CV *proto)
 {
     CV *cv;
-    MUTEX_LOCK(&PL_cred_mutex);                /* XXX create separate mutex */
+    LOCK_CRED_MUTEX;                   /* XXX create separate mutex */
     cv = cv_clone2(proto, CvOUTSIDE(proto));
-    MUTEX_UNLOCK(&PL_cred_mutex);      /* XXX create separate mutex */
+    UNLOCK_CRED_MUTEX;                 /* XXX create separate mutex */
     return cv;
 }
 
@@ -4138,7 +4228,7 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
 {
     dTHR;
 
-    if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_UNSAFE)) {
+    if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_PROTOTYPE)) {
        SV* msg = sv_newmortal();
        SV* name = Nullsv;
 
@@ -4146,7 +4236,7 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
            gv_efullname3(name = sv_newmortal(), gv, Nullch);
        sv_setpv(msg, "Prototype mismatch:");
        if (name)
-           Perl_sv_catpvf(aTHX_ msg, " sub %_", name);
+           Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name);
        if (SvPOK(cv))
            Perl_sv_catpvf(aTHX_ msg, " (%s)", SvPVX(cv));
        sv_catpv(msg, " vs ");
@@ -4154,7 +4244,7 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
            Perl_sv_catpvf(aTHX_ msg, "(%s)", p);
        else
            sv_catpv(msg, "none");
-       Perl_warner(aTHX_ WARN_UNSAFE, "%_", msg);
+       Perl_warner(aTHX_ WARN_PROTOTYPE, "%"SVf, msg);
     }
 }
 
@@ -4171,10 +4261,10 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv)
 {
     SV *sv = Nullsv;
 
-    if(!o)
+    if (!o)
        return Nullsv;
  
-    if(o->op_type == OP_LINESEQ && cLISTOPo->op_first) 
+    if (o->op_type == OP_LINESEQ && cLISTOPo->op_first) 
        o = cLISTOPo->op_first->op_sibling;
 
     for (; o; o = o->op_next) {
@@ -4229,14 +4319,26 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 {
     dTHR;
     STRLEN n_a;
-    char *name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
-    GV *gv = gv_fetchpv(name ? name : "__ANON__",
-                       GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT),
-                       SVt_PVCV);
+    char *name;
+    char *aname;
+    GV *gv;
     char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch;
     register CV *cv=0;
     I32 ix;
 
+    name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
+    if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) {
+       SV *sv = sv_newmortal();
+       Perl_sv_setpvf(aTHX_ sv, "__ANON__[%s:%"IVdf"]",
+                      CopFILE(PL_curcop), (IV)CopLINE(PL_curcop));
+       aname = SvPVX(sv);
+    }
+    else
+       aname = Nullch;
+    gv = gv_fetchpv(name ? name : (aname ? aname : "__ANON__"),
+                   GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT),
+                   SVt_PVCV);
+
     if (o)
        SAVEFREEOP(o);
     if (proto)
@@ -4248,9 +4350,9 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                                           maximum a prototype before. */
        if (SvTYPE(gv) > SVt_NULL) {
            if (!SvPOK((SV*)gv) && !(SvIOK((SV*)gv) && SvIVX((SV*)gv) == -1)
-               && ckWARN_d(WARN_UNSAFE))
+               && ckWARN_d(WARN_PROTOTYPE))
            {
-               Perl_warner(aTHX_ WARN_UNSAFE, "Runaway prototype");
+               Perl_warner(aTHX_ WARN_PROTOTYPE, "Runaway prototype");
            }
            cv_ckproto((CV*)gv, NULL, ps);
        }
@@ -4282,13 +4384,10 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name);
            if (!block)
                goto withattrs;
-           if(const_sv = cv_const_sv(cv))
+           if (const_sv = cv_const_sv(cv))
                const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv));
-           if ((const_sv && const_changed) || ckWARN(WARN_REDEFINE) 
-                                       && !(CvGV(cv) && GvSTASH(CvGV(cv))
-                                       && HvNAME(GvSTASH(CvGV(cv)))
-                                       && strEQ(HvNAME(GvSTASH(CvGV(cv))),
-                                                "autouse"))) {
+           if ((const_sv || const_changed) && ckWARN(WARN_REDEFINE))
+           {
                line_t oldline = CopLINE(PL_curcop);
                CopLINE_set(PL_curcop, PL_copline);
                Perl_warner(aTHX_ WARN_REDEFINE,
@@ -4443,15 +4542,17 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        }
     }
 
-    if (name) {
+    if (name || aname) {
        char *s;
+       char *tname = (name ? name : aname);
 
        if (PERLDB_SUBLINE && PL_curstash != PL_debstash) {
            SV *sv = NEWSV(0,0);
            SV *tmpstr = sv_newmortal();
            GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV);
-           CV *cv;
+           CV *pcv;
            HV *hv;
+           char *t;
 
            Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld",
                           CopFILE(PL_curcop),
@@ -4460,21 +4561,22 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            hv_store(GvHV(PL_DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0);
            hv = GvHVn(db_postponed);
            if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr))
-                 && (cv = GvCV(db_postponed))) {
+               && (pcv = GvCV(db_postponed)))
+           {
                dSP;
                PUSHMARK(SP);
                XPUSHs(tmpstr);
                PUTBACK;
-               call_sv((SV*)cv, G_DISCARD);
+               call_sv((SV*)pcv, G_DISCARD);
            }
        }
 
-       if ((s = strrchr(name,':')))
+       if ((s = strrchr(tname,':')))
            s++;
        else
-           s = name;
+           s = tname;
 
-       if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I')
+       if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
            goto done;
 
        if (strEQ(s, "BEGIN")) {
@@ -4504,12 +4606,12 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            av_store(PL_endav, 0, SvREFCNT_inc(cv));
            GvCV(gv) = 0;
        }
-       else if (strEQ(s, "STOP") && !PL_error_count) {
-           if (!PL_stopav)
-               PL_stopav = newAV();
+       else if (strEQ(s, "CHECK") && !PL_error_count) {
+           if (!PL_checkav)
+               PL_checkav = newAV();
            DEBUG_x( dump_sub(gv) );
-           av_unshift(PL_stopav, 1);
-           av_store(PL_stopav, 0, SvREFCNT_inc(cv));
+           av_unshift(PL_checkav, 1);
+           av_store(PL_checkav, 0, SvREFCNT_inc(cv));
            GvCV(gv) = 0;
        }
        else if (strEQ(s, "INIT") && !PL_error_count) {
@@ -4528,6 +4630,15 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 }
 
 /* XXX unsafe for threads if eval_owner isn't held */
+/*
+=for apidoc newCONSTSUB
+
+Creates a constant sub equivalent to Perl C<sub FOO () { 123 }> which is
+eligible for inlining at compile-time.
+
+=cut
+*/
+
 void
 Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
 {
@@ -4562,6 +4673,14 @@ Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
     LEAVE;
 }
 
+/*
+=for apidoc U||newXS
+
+Used by C<xsubpp> to hook up XSUBs as Perl subs.
+
+=cut
+*/
+
 CV *
 Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
 {
@@ -4620,7 +4739,7 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
        else
            s = name;
 
-       if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I')
+       if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
            goto done;
 
        if (strEQ(s, "BEGIN")) {
@@ -4636,11 +4755,11 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
            av_store(PL_endav, 0, SvREFCNT_inc(cv));
            GvCV(gv) = 0;
        }
-       else if (strEQ(s, "STOP")) {
-           if (!PL_stopav)
-               PL_stopav = newAV();
-           av_unshift(PL_stopav, 1);
-           av_store(PL_stopav, 0, SvREFCNT_inc(cv));
+       else if (strEQ(s, "CHECK")) {
+           if (!PL_checkav)
+               PL_checkav = newAV();
+           av_unshift(PL_checkav, 1);
+           av_store(PL_checkav, 0, SvREFCNT_inc(cv));
            GvCV(gv) = 0;
        }
        else if (strEQ(s, "INIT")) {
@@ -4910,11 +5029,22 @@ Perl_ck_delete(pTHX_ OP *o)
     o->op_private = 0;
     if (o->op_flags & OPf_KIDS) {
        OP *kid = cUNOPo->op_first;
-       if (kid->op_type == OP_HSLICE)
+       switch (kid->op_type) {
+       case OP_ASLICE:
+           o->op_flags |= OPf_SPECIAL;
+           /* FALL THROUGH */
+       case OP_HSLICE:
            o->op_private |= OPpSLICE;
-       else if (kid->op_type != OP_HELEM)
-           Perl_croak(aTHX_ "%s argument is not a HASH element or slice",
+           break;
+       case OP_AELEM:
+           o->op_flags |= OPf_SPECIAL;
+           /* FALL THROUGH */
+       case OP_HELEM:
+           break;
+       default:
+           Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element or slice",
                  PL_op_desc[o->op_type]);
+       }
        null(kid);
     }
     return o;
@@ -5000,8 +5130,18 @@ Perl_ck_exists(pTHX_ OP *o)
     o = ck_fun(o);
     if (o->op_flags & OPf_KIDS) {
        OP *kid = cUNOPo->op_first;
-       if (kid->op_type != OP_HELEM)
-           Perl_croak(aTHX_ "%s argument is not a HASH element", PL_op_desc[o->op_type]);
+       if (kid->op_type == OP_ENTERSUB) {
+           (void) ref(kid, o->op_type);
+           if (kid->op_type != OP_RV2CV && !PL_error_count)
+               Perl_croak(aTHX_ "%s argument is not a subroutine name",
+                          PL_op_desc[o->op_type]);
+           o->op_private |= OPpEXISTS_SUB;
+       }
+       else if (kid->op_type == OP_AELEM)
+           o->op_flags |= OPf_SPECIAL;
+       else if (kid->op_type != OP_HELEM)
+           Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element",
+                      PL_op_desc[o->op_type]);
        null(kid);
     }
     return o;
@@ -5114,7 +5254,7 @@ Perl_ck_rvconst(pTHX_ register OP *o)
            kid->op_type = OP_GV;
            SvREFCNT_dec(kid->op_sv);
 #ifdef USE_ITHREADS
-           /* XXXXXX hack: dependence on sizeof(PADOP) <= sizeof(SVOP) */
+           /* XXX hack: dependence on sizeof(PADOP) <= sizeof(SVOP) */
            kPADOP->op_padix = pad_alloc(OP_GV, SVs_PADTMP);
            GvIN_PAD_on(gv);
            PL_curpad[kPADOP->op_padix] = SvREFCNT_inc(gv);
@@ -5224,8 +5364,8 @@ Perl_ck_fun(pTHX_ OP *o)
                    char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
                    OP *newop = newAVREF(newGVOP(OP_GV, 0,
                        gv_fetchpv(name, TRUE, SVt_PVAV) ));
-                   if (ckWARN(WARN_SYNTAX))
-                       Perl_warner(aTHX_ WARN_SYNTAX,
+                   if (ckWARN(WARN_DEPRECATED))
+                       Perl_warner(aTHX_ WARN_DEPRECATED,
                            "Array @%s missing the @ in argument %"IVdf" of %s()",
                            name, (IV)numargs, PL_op_desc[type]);
                    op_free(kid);
@@ -5244,8 +5384,8 @@ Perl_ck_fun(pTHX_ OP *o)
                    char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
                    OP *newop = newHVREF(newGVOP(OP_GV, 0,
                        gv_fetchpv(name, TRUE, SVt_PVHV) ));
-                   if (ckWARN(WARN_SYNTAX))
-                       Perl_warner(aTHX_ WARN_SYNTAX,
+                   if (ckWARN(WARN_DEPRECATED))
+                       Perl_warner(aTHX_ WARN_DEPRECATED,
                            "Hash %%%s missing the %% in argument %"IVdf" of %s()",
                            name, (IV)numargs, PL_op_desc[type]);
                    op_free(kid);
@@ -5286,26 +5426,46 @@ Perl_ck_fun(pTHX_ OP *o)
                    else {
                        I32 flags = OPf_SPECIAL;
                        I32 priv = 0;
+                       PADOFFSET targ = 0;
+
                        /* is this op a FH constructor? */
                        if (is_handle_constructor(o,numargs)) {
-                           flags   = 0;                         
-                           /* Set a flag to tell rv2gv to vivify 
+                           char *name = Nullch;
+                           STRLEN len;
+
+                           flags = 0;
+                           /* Set a flag to tell rv2gv to vivify
                             * need to "prove" flag does not mean something
                             * else already - NI-S 1999/05/07
-                            */ 
-                           priv = OPpDEREF; 
-#if 0
-                           /* Helps with open($array[$n],...) 
-                              but is too simplistic - need to do selectively
-                           */
-                           mod(kid,type);
-#endif
+                            */
+                           priv = OPpDEREF;
+                           if (kid->op_type == OP_PADSV) {
+                               SV **namep = av_fetch(PL_comppad_name,
+                                                     kid->op_targ, 4);
+                               if (namep && *namep)
+                                   name = SvPV(*namep, len);
+                           }
+                           else if (kid->op_type == OP_RV2SV
+                                    && kUNOP->op_first->op_type == OP_GV)
+                           {
+                               GV *gv = cGVOPx_gv(kUNOP->op_first);
+                               name = GvNAME(gv);
+                               len = GvNAMELEN(gv);
+                           }
+                           if (name) {
+                               SV *namesv;
+                               targ = pad_alloc(OP_RV2GV, SVs_PADTMP);
+                               namesv = PL_curpad[targ];
+                               SvUPGRADE(namesv, SVt_PV);
+                               if (*name != '$')
+                                   sv_setpvn(namesv, "$", 1);
+                               sv_catpvn(namesv, name, len);
+                           }
                        }
                        kid->op_sibling = 0;
                        kid = newUNOP(OP_RV2GV, flags, scalar(kid));
-                       if (priv) {
-                           kid->op_private |= priv;
-                       }
+                       kid->op_targ = targ;
+                       kid->op_private |= priv;
                    }
                    kid->op_sibling = sibl;
                    *tokid = kid;
@@ -5344,24 +5504,25 @@ Perl_ck_glob(pTHX_ OP *o)
 {
     GV *gv;
 
+    o = ck_fun(o);
     if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling)
        append_elem(OP_GLOB, o, newDEFSVOP());
 
     if (!((gv = gv_fetchpv("glob", FALSE, SVt_PVCV)) && GvIMPORTED_CV(gv)))
        gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
 
-#if defined(PERL_INTERNAL_GLOB) && !defined(MINIPERL_BUILD)
+#if !defined(PERL_EXTERNAL_GLOB)
     /* XXX this can be tightened up and made more failsafe. */
     if (!gv) {
        OP *modname = newSVOP(OP_CONST, 0, newSVpvn("File::Glob", 10));
        modname->op_private |= OPpCONST_BARE;
        ENTER;
        utilize(1, start_subparse(FALSE, 0), Nullop, modname,
-               newSVOP(OP_CONST, 0, newSVpvn("globally", 8)));
+               newSVOP(OP_CONST, 0, newSVpvn(":globally", 9)));
        gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
        LEAVE;
     }
-#endif /* PERL_INTERNAL_GLOB && !MINIPERL_BUILD */
+#endif /* PERL_EXTERNAL_GLOB */
 
     if (gv && GvIMPORTED_CV(gv)) {
        append_elem(OP_GLOB, o,
@@ -5382,7 +5543,7 @@ Perl_ck_glob(pTHX_ OP *o)
     gv_IOadd(gv);
     append_elem(OP_GLOB, o, newGVOP(OP_GV, 0, gv));
     scalarkids(o);
-    return ck_fun(o);
+    return o;
 }
 
 OP *
@@ -5482,7 +5643,7 @@ Perl_ck_defined(pTHX_ OP *o)              /* 19990527 MJD */
            break;                      /* Globals via GV can be undef */ 
        case OP_PADHV:
            Perl_warner(aTHX_ WARN_DEPRECATED,
-                       "defined(%hash) is deprecated");
+                       "defined(%%hash) is deprecated");
            Perl_warner(aTHX_ WARN_DEPRECATED,
                        "(Maybe you should just omit the defined()?)\n");
            break;
@@ -5559,7 +5720,9 @@ Perl_ck_sassign(pTHX_ OP *o)
     OP *kid = cLISTOPo->op_first;
     /* has a disposable target? */
     if ((PL_opargs[kid->op_type] & OA_TARGLEX)
-       && !(kid->op_flags & OPf_STACKED))
+       && !(kid->op_flags & OPf_STACKED)
+       /* Cannot steal the second time! */
+       && !(kid->op_private & OPpTARGET_MY))
     {
        OP *kkid = kid->op_sibling;
 
@@ -5567,31 +5730,6 @@ Perl_ck_sassign(pTHX_ OP *o)
        if (kkid && kkid->op_type == OP_PADSV
            && !(kkid->op_private & OPpLVAL_INTRO))
        {
-           /* Concat has problems if target is equal to right arg. */
-           if (kid->op_type == OP_CONCAT) {
-               if (kLISTOP->op_first->op_sibling->op_type == OP_PADSV
-                   && kLISTOP->op_first->op_sibling->op_targ == kkid->op_targ)
-                   return o;
-           }
-           else if (kid->op_type == OP_JOIN) {
-               /* do_join has problems if the arguments coincide with target.
-                  In fact the second argument *can* safely coincide,
-                  but ignore=pessimize this rare occasion. */
-               OP *arg = kLISTOP->op_first->op_sibling; /* Skip PUSHMARK */
-
-               while (arg) {
-                   if (arg->op_type == OP_PADSV
-                       && arg->op_targ == kkid->op_targ)
-                       return o;
-                   arg = arg->op_sibling;
-               }
-           }
-           else if (kid->op_type == OP_QUOTEMETA) {
-               /* quotemeta has problems if the argument coincides with target. */
-               if (kLISTOP->op_first->op_type == OP_PADSV
-                   && kLISTOP->op_first->op_targ == kkid->op_targ)
-                   return o;
-           }
            kid->op_targ = kkid->op_targ;
            kkid->op_targ = 0;
            /* Now we do not need PADSV and SASSIGN. */
@@ -5826,12 +5964,12 @@ S_simplify_sort(pTHX_ OP *o)
     if (kUNOP->op_first->op_type != OP_GV)
        return;
     kid = kUNOP->op_first;                             /* get past rv2sv */
-    gv = kGVOP;
+    gv = kGVOP_gv;
     if (GvSTASH(gv) != PL_curstash)
        return;
     if (strEQ(GvNAME(gv), "a"))
        reversed = 0;
-    else if(strEQ(GvNAME(gv), "b"))
+    else if (strEQ(GvNAME(gv), "b"))
        reversed = 1;
     else
        return;
@@ -5842,7 +5980,7 @@ S_simplify_sort(pTHX_ OP *o)
     if (kUNOP->op_first->op_type != OP_GV)
        return;
     kid = kUNOP->op_first;                             /* get past rv2sv */
-    gv = kGVOP;
+    gv = kGVOP_gv;
     if (GvSTASH(gv) != PL_curstash
        || ( reversed
            ? strNE(GvNAME(gv), "a")
@@ -5952,7 +6090,7 @@ Perl_ck_subr(pTHX_ OP *o)
        null(cvop);             /* disable rv2cv */
        tmpop = (SVOP*)((UNOP*)cvop)->op_first;
        if (tmpop->op_type == OP_GV && !(o->op_private & OPpENTERSUB_AMPER)) {
-           GV *gv = cGVOPx(tmpop);
+           GV *gv = cGVOPx_gv(tmpop);
            cv = GvCVu(gv);
            if (!cv)
                tmpop->op_private |= OPpEARLY_CV;
@@ -6020,7 +6158,7 @@ Perl_ck_subr(pTHX_ OP *o)
                                (gvop = ((UNOP*)gvop)->op_first) &&
                                gvop->op_type == OP_GV)
                            {
-                               GV *gv = cGVOPx(gvop);
+                               GV *gv = cGVOPx_gv(gvop);
                                OP *sibling = o2->op_sibling;
                                SV *n = newSVpvn("",0);
                                op_free(o2);
@@ -6175,26 +6313,13 @@ Perl_peep(pTHX_ register OP *o)
        case OP_UCFIRST:
        case OP_LC:
        case OP_LCFIRST:
-           if ( o->op_next && o->op_next->op_type == OP_STRINGIFY
-                && !(o->op_next->op_private & OPpTARGET_MY) )
-               null(o->op_next);
-           o->op_seq = PL_op_seqmax++;
-           break;
        case OP_CONCAT:
        case OP_JOIN:
        case OP_QUOTEMETA:
            if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
                if (o->op_next->op_private & OPpTARGET_MY) {
-                   if ((o->op_flags & OPf_STACKED) /* chained concats */
-                       || (o->op_type == OP_CONCAT
-           /* Concat has problems if target is equal to right arg. */
-                           && (((LISTOP*)o)->op_first->op_sibling->op_type
-                               == OP_PADSV)
-                           && (((LISTOP*)o)->op_first->op_sibling->op_targ
-                               == o->op_next->op_targ)))
-                   {
+                   if (o->op_flags & OPf_STACKED) /* chained concats */
                        goto ignore_optimization;
-                   }
                    else {
                        o->op_targ = o->op_next->op_targ;
                        o->op_next->op_targ = 0;
@@ -6235,7 +6360,8 @@ Perl_peep(pTHX_ register OP *o)
            if (o->op_next->op_type == OP_RV2SV) {
                if (!(o->op_next->op_private & OPpDEREF)) {
                    null(o->op_next);
-                   o->op_private |= o->op_next->op_private & OPpLVAL_INTRO;
+                   o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO
+                                                              | OPpOUR_INTRO);
                    o->op_next = o->op_next->op_next;
                    o->op_type = OP_GVSV;
                    o->op_ppaddr = PL_ppaddr[OP_GVSV];
@@ -6262,17 +6388,17 @@ Perl_peep(pTHX_ register OP *o)
                    o->op_type = OP_AELEMFAST;
                    o->op_ppaddr = PL_ppaddr[OP_AELEMFAST];
                    o->op_private = (U8)i;
-                   gv = cGVOPo;
+                   gv = cGVOPo_gv;
                    GvAVn(gv);
                }
            }
-           else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_UNSAFE)) {
-               GV *gv = cGVOPo;
+           else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
+               GV *gv = cGVOPo_gv;
                if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX(GvCV(gv))) {
                    /* XXX could check prototype here instead of just carping */
                    SV *sv = sv_newmortal();
                    gv_efullname3(sv, gv, Nullch);
-                   Perl_warner(aTHX_ WARN_UNSAFE,
+                   Perl_warner(aTHX_ WARN_PROTOTYPE,
                                "%s() called too early to check prototype",
                                SvPV_nolen(sv));
                }
@@ -6320,8 +6446,10 @@ Perl_peep(pTHX_ register OP *o)
                    line_t oldline = CopLINE(PL_curcop);
 
                    CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next));
-                   Perl_warner(aTHX_ WARN_SYNTAX, "Statement unlikely to be reached");
-                   Perl_warner(aTHX_ WARN_SYNTAX, "(Maybe you meant system() when you said exec()?)\n");
+                   Perl_warner(aTHX_ WARN_EXEC,
+                               "Statement unlikely to be reached");
+                   Perl_warner(aTHX_ WARN_EXEC,
+                               "(Maybe you meant system() when you said exec()?)\n");
                    CopLINE_set(PL_curcop, oldline);
                }
            }
@@ -6331,11 +6459,12 @@ Perl_peep(pTHX_ register OP *o)
            UNOP *rop;
            SV *lexname;
            GV **fields;
-           SV **svp, **indsvp;
+           SV **svp, **indsvp, *sv;
            I32 ind;
            char *key;
            STRLEN keylen;
        
+           o->op_seq = PL_op_seqmax++;
            if ((o->op_private & (OPpLVAL_INTRO))
                || ((BINOP*)o)->op_last->op_type != OP_CONST)
                break;
@@ -6348,7 +6477,7 @@ Perl_peep(pTHX_ register OP *o)
            fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
            if (!fields || !GvHV(*fields))
                break;
-           svp = &cSVOPx_sv(((BINOP*)o)->op_last);
+           svp = cSVOPx_svp(((BINOP*)o)->op_last);
            key = SvPV(*svp, keylen);
            indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
            if (!indsvp) {
@@ -6362,8 +6491,76 @@ Perl_peep(pTHX_ register OP *o)
            rop->op_ppaddr = PL_ppaddr[OP_RV2AV];
            o->op_type = OP_AELEM;
            o->op_ppaddr = PL_ppaddr[OP_AELEM];
+           sv = newSViv(ind);
+           if (SvREADONLY(*svp))
+               SvREADONLY_on(sv);
+           SvFLAGS(sv) |= (SvFLAGS(*svp)
+                           & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY));
            SvREFCNT_dec(*svp);
-           *svp = newSViv(ind);
+           *svp = sv;
+           break;
+       }
+       
+       case OP_HSLICE: {
+           UNOP *rop;
+           SV *lexname;
+           GV **fields;
+           SV **svp, **indsvp, *sv;
+           I32 ind;
+           char *key;
+           STRLEN keylen;
+           SVOP *first_key_op, *key_op;
+
+           o->op_seq = PL_op_seqmax++;
+           if ((o->op_private & (OPpLVAL_INTRO))
+               /* I bet there's always a pushmark... */
+               || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
+               /* hmmm, no optimization if list contains only one key. */
+               break;
+           rop = (UNOP*)((LISTOP*)o)->op_last;
+           if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
+               break;
+           lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
+           if (!SvOBJECT(lexname))
+               break;
+           fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+           if (!fields || !GvHV(*fields))
+               break;
+           /* Again guessing that the pushmark can be jumped over.... */
+           first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
+               ->op_first->op_sibling;
+           /* Check that the key list contains only constants. */
+           for (key_op = first_key_op; key_op;
+                key_op = (SVOP*)key_op->op_sibling)
+               if (key_op->op_type != OP_CONST)
+                   break;
+           if (key_op)
+               break;
+           rop->op_type = OP_RV2AV;
+           rop->op_ppaddr = PL_ppaddr[OP_RV2AV];
+           o->op_type = OP_ASLICE;
+           o->op_ppaddr = PL_ppaddr[OP_ASLICE];
+           for (key_op = first_key_op; key_op;
+                key_op = (SVOP*)key_op->op_sibling) {
+               svp = cSVOPx_svp(key_op);
+               key = SvPV(*svp, keylen);
+               indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
+               if (!indsvp) {
+                   Perl_croak(aTHX_ "No such pseudo-hash field \"%s\" "
+                              "in variable %s of type %s",
+                         key, SvPV(lexname, n_a), HvNAME(SvSTASH(lexname)));
+               }
+               ind = SvIV(*indsvp);
+               if (ind < 1)
+                   Perl_croak(aTHX_ "Bad index while coercing array into hash");
+               sv = newSViv(ind);
+               if (SvREADONLY(*svp))
+                   SvREADONLY_on(sv);
+               SvFLAGS(sv) |= (SvFLAGS(*svp)
+                               & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY));
+               SvREFCNT_dec(*svp);
+               *svp = sv;
+           }
            break;
        }