This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [PATCH] Abstract "utility" information from installman
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 6729ca0..5a51f9b 100644 (file)
--- a/op.c
+++ b/op.c
@@ -103,30 +103,6 @@ S_no_bareword_allowed(pTHX_ OP *o)
                     SvPV_nolen(cSVOPo_sv)));
 }
 
-STATIC U8*
-S_trlist_upgrade(pTHX_ U8** sp, U8** ep)
-{
-    U8 *s = *sp;
-    U8 *e = *ep;
-    U8 *d;
-
-    Newz(801, d, (e - s) * 2, U8);
-    *sp = d;
-
-    while (s < e) {
-        if (*s < 0x80 || *s == 0xff)
-            *d++ = *s++;
-       else {
-            U8 c = *s++;
-            *d++ = ((c >> 6)         | 0xc0);
-            *d++ = ((c       & 0x3f) | 0x80);
-        }
-    }
-    *ep = d;
-    return *sp;
-}
-  
-
 /* "register" allocation */
 
 PADOFFSET
@@ -759,8 +735,8 @@ Perl_op_free(pTHX_ OP *o)
 #endif
 }
 
-STATIC void
-S_op_clear(pTHX_ OP *o)
+void
+Perl_op_clear(pTHX_ OP *o)
 {
     switch (o->op_type) {
     case OP_NULL:      /* Was holding old type, if any. */
@@ -843,6 +819,29 @@ S_op_clear(pTHX_ OP *o)
     case OP_MATCH:
     case OP_QR:
 clear_pmop:
+       {
+           HV *pmstash = PmopSTASH(cPMOPo);
+           if (pmstash && SvREFCNT(pmstash)) {
+               PMOP *pmop = HvPMROOT(pmstash);
+               PMOP *lastpmop = NULL;
+               while (pmop) {
+                   if (cPMOPo == pmop) {
+                       if (lastpmop)
+                           lastpmop->op_pmnext = pmop->op_pmnext;
+                       else
+                           HvPMROOT(pmstash) = pmop->op_pmnext;
+                       break;
+                   }
+                   lastpmop = pmop;
+                   pmop = pmop->op_pmnext;
+               }
+#ifdef USE_ITHREADS
+               Safefree(PmopSTASHPV(cPMOPo));
+#else
+               /* NOTE: PMOP.op_pmstash is not refcounted */
+#endif
+           }
+       }
        cPMOPo->op_pmreplroot = Nullop;
        ReREFCNT_dec(cPMOPo->op_pmregexp);
        cPMOPo->op_pmregexp = (REGEXP*)NULL;
@@ -872,8 +871,8 @@ S_cop_free(pTHX_ COP* cop)
        SvREFCNT_dec(cop->cop_io);
 }
 
-STATIC void
-S_null(pTHX_ OP *o)
+void
+Perl_op_null(pTHX_ OP *o)
 {
     if (o->op_type == OP_NULL)
        return;
@@ -954,8 +953,6 @@ Perl_scalar(pTHX_ OP *o)
 
     switch (o->op_type) {
     case OP_REPEAT:
-       if (o->op_private & OPpREPEAT_DOLIST)
-           null(((LISTOP*)cBINOPo->op_first)->op_first);
        scalar(cBINOPo->op_first);
        break;
     case OP_OR:
@@ -1140,6 +1137,9 @@ Perl_scalarvoid(pTHX_ OP *o)
        else {
            if (ckWARN(WARN_VOID)) {
                useless = "a constant";
+               /* the constants 0 and 1 are permitted as they are
+                  conventionally used as dummies in constructs like
+                       1 while some_condition_with_side_effects;  */
                if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0))
                    useless = 0;
                else if (SvPOK(sv)) {
@@ -1156,7 +1156,7 @@ Perl_scalarvoid(pTHX_ OP *o)
                }
            }
        }
-       null(o);                /* don't execute or even remember it */
+       op_null(o);             /* don't execute or even remember it */
        break;
 
     case OP_POSTINC:
@@ -1361,31 +1361,6 @@ Perl_mod(pTHX_ OP *o, I32 type)
        PL_modcount++;
        return o;
     case OP_CONST:
-        if (o->op_private & (OPpCONST_BARE) && 
-                !(type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN)) {
-            SV *sv = ((SVOP*)o)->op_sv;
-            GV *gv;
-
-            /* Could be a filehandle */
-            if (gv = gv_fetchpv(SvPV_nolen(sv), FALSE, SVt_PVIO)) {
-                OP* gvio = newUNOP(OP_RV2GV, 0, newGVOP(OP_GV, 0, gv));
-                op_free(o);
-                o = gvio;
-            } else {
-                /* OK, it's a sub */
-                OP* enter;
-                gv = gv_fetchpv(SvPV_nolen(sv), TRUE, SVt_PVCV);
-
-                enter = newUNOP(OP_ENTERSUB,0, 
-                        newUNOP(OP_RV2CV, 0, 
-                            newGVOP(OP_GV, 0, gv)
-                        ));
-                enter->op_private |= OPpLVAL_INTRO;
-                op_free(o);
-                o = enter;
-            }
-            break;
-        }
        if (!(o->op_private & (OPpCONST_ARYBASE)))
            goto nomod;
        if (PL_eval_start && PL_eval_start->op_type == OP_CONST) {
@@ -1411,7 +1386,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
            o->op_type = OP_RV2CV;              /* entersub => rv2cv */
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
            assert(cUNOPo->op_first->op_type == OP_NULL);
-           null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */
+           op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */
            break;
        }
        else {                          /* lvalue subroutine call */
@@ -1568,7 +1543,6 @@ Perl_mod(pTHX_ OP *o, I32 type)
     case OP_AASSIGN:
     case OP_NEXTSTATE:
     case OP_DBSTATE:
-    case OP_REFGEN:
     case OP_CHOMP:
        PL_modcount = RETURN_UNLIMITED_NUMBER;
        break;
@@ -1784,7 +1758,7 @@ Perl_ref(pTHX_ OP *o, I32 type)
            o->op_type = OP_RV2CV;             /* entersub => rv2cv */
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
            assert(cUNOPo->op_first->op_type == OP_NULL);
-           null(((LISTOP*)cUNOPo->op_first)->op_first);        /* disable pushmark */
+           op_null(((LISTOP*)cUNOPo->op_first)->op_first);     /* disable pushmark */
            o->op_flags |= OPf_SPECIAL;
        }
        break;
@@ -1957,6 +1931,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? */
+        if (attrs) {
+            GV *gv = cGVOPx_gv(cUNOPo->op_first);
+            PL_in_my = FALSE;
+            PL_in_my_stash = Nullhv;
+            apply_attrs(GvSTASH(gv),
+                        (type == OP_RV2SV ? GvSV(gv) :
+                         type == OP_RV2AV ? (SV*)GvAV(gv) :
+                         type == OP_RV2HV ? (SV*)GvHV(gv) : (SV*)gv),
+                        attrs);
+        }
        o->op_private |= OPpOUR_INTRO;
        return o;
     } else if (type != OP_PADSV &&
@@ -2086,7 +2070,7 @@ Perl_scope(pTHX_ OP *o)
                o->op_ppaddr = PL_ppaddr[OP_SCOPE];
                kid = ((LISTOP*)o)->op_first;
                if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)
-                   null(kid);
+                   op_null(kid);
            }
            else
                o = newLISTOP(OP_SCOPE, 0, o, Nullop);
@@ -2391,16 +2375,13 @@ Perl_gen_constant_list(pTHX_ register OP *o)
 OP *
 Perl_convert(pTHX_ I32 type, I32 flags, OP *o)
 {
-    OP *kid;
-    OP *last = 0;
-
     if (!o || o->op_type != OP_LIST)
        o = newLISTOP(OP_LIST, 0, o, Nullop);
     else
        o->op_flags &= ~OPf_WANT;
 
     if (!(PL_opargs[type] & OA_MARK))
-       null(cLISTOPo->op_first);
+       op_null(cLISTOPo->op_first);
 
     o->op_type = type;
     o->op_ppaddr = PL_ppaddr[type];
@@ -2510,7 +2491,7 @@ Perl_force_list(pTHX_ OP *o)
 {
     if (!o || o->op_type != OP_LIST)
        o = newLISTOP(OP_LIST, 0, o, Nullop);
-    null(o);
+    op_null(o);
     return o;
 }
 
@@ -2621,15 +2602,16 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last)
 }
 
 static int
-utf8compare(const void *a, const void *b)
-{
-    int i;
-    for (i = 0; i < 10; i++) {
-       if ((*(U8**)a)[i] < (*(U8**)b)[i])
-           return -1;
-       if ((*(U8**)a)[i] > (*(U8**)b)[i])
-           return 1;
-    }
+uvcompare(const void *a, const void *b)
+{
+    if (*((UV *)a) < (*(UV *)b))
+       return -1;
+    if (*((UV *)a) > (*(UV *)b))
+       return 1;
+    if (*((UV *)a+1) < (*(UV *)b+1))
+       return -1;
+    if (*((UV *)a+1) > (*(UV *)b+1))
+       return 1;
     return 0;
 }
 
@@ -2650,6 +2632,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
     I32 grows = 0;
     register short *tbl;
 
+    PL_hints |= HINT_BLOCK_SCOPE;
     complement = o->op_private & OPpTRANS_COMPLEMENT;
     del                = o->op_private & OPpTRANS_DELETE;
     squash     = o->op_private & OPpTRANS_SQUASH;
@@ -2680,60 +2663,82 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        U32 final;
        I32 from_utf    = o->op_private & OPpTRANS_FROM_UTF;
        I32 to_utf      = o->op_private & OPpTRANS_TO_UTF;
-       U8* tsave = from_utf ? NULL : trlist_upgrade(&t, &tend);
-       U8* rsave = to_utf   ? NULL : trlist_upgrade(&r, &rend);
+       U8* tsave = NULL;
+       U8* rsave = NULL;
+
+       if (!from_utf) {
+           STRLEN len = tlen;
+           tsave = t = bytes_to_utf8(t, &len);
+           tend = t + len;
+       }
+       if (!to_utf && rlen) {
+           STRLEN len = rlen;
+           rsave = r = bytes_to_utf8(r, &len);
+           rend = r + len;
+       }
+
+/* There are several snags with this code on EBCDIC:
+   1. 0xFF is a legal UTF-EBCDIC byte (there are no illegal bytes).
+   2. scan_const() in toke.c has encoded chars in native encoding which makes
+      ranges at least in EBCDIC 0..255 range the bottom odd.
+*/
 
        if (complement) {
            U8 tmpbuf[UTF8_MAXLEN+1];
-           U8** cp;
-           I32* cl;
+           UV *cp;
            UV nextmin = 0;
-           New(1109, cp, tlen, U8*);
+           New(1109, cp, 2*tlen, UV);
            i = 0;
            transv = newSVpvn("",0);
            while (t < tend) {
-               cp[i++] = t;
-               t += UTF8SKIP(t);
-               if (*t == 0xff) {
+               cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, 0);
+               t += ulen;
+               if (t < tend && NATIVE_TO_UTF(*t) == 0xff) {
                    t++;
-                   t += UTF8SKIP(t);
+                   cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, 0);
+                   t += ulen;
+               }
+               else {
+                cp[2*i+1] = cp[2*i];
                }
+               i++;
            }
-           qsort(cp, i, sizeof(U8*), utf8compare);
+           qsort(cp, i, 2*sizeof(UV), uvcompare);
            for (j = 0; j < i; j++) {
-               U8 *s = cp[j];
-               I32 cur = j < i ? cp[j+1] - s : tend - s;
-               UV  val = utf8_to_uv(s, cur, &ulen, 0);
-               s += ulen;
+               UV  val = cp[2*j];
                diff = val - nextmin;
                if (diff > 0) {
-                   t = uv_to_utf8(tmpbuf,nextmin);
+                   t = uvuni_to_utf8(tmpbuf,nextmin);
                    sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf);
                    if (diff > 1) {
-                       t = uv_to_utf8(tmpbuf, val - 1);
-                       sv_catpvn(transv, "\377", 1);
+                       U8  range_mark = UTF_TO_NATIVE(0xff);
+                       t = uvuni_to_utf8(tmpbuf, val - 1);
+                       sv_catpvn(transv, (char *)&range_mark, 1);
                        sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf);
                    }
                }
-               if (*s == 0xff)
-                   val = utf8_to_uv(s+1, cur - 1, &ulen, 0);
+               val = cp[2*j+1];
                if (val >= nextmin)
                    nextmin = val + 1;
            }
-           t = uv_to_utf8(tmpbuf,nextmin);
+           t = uvuni_to_utf8(tmpbuf,nextmin);
            sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf);
-           t = uv_to_utf8(tmpbuf, 0x7fffffff);
-           sv_catpvn(transv, "\377", 1);
+           {
+               U8 range_mark = UTF_TO_NATIVE(0xff);
+               sv_catpvn(transv, (char *)&range_mark, 1);
+           }
+           t = uvuni_to_utf8(tmpbuf, 0x7fffffff);
            sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf);
            t = (U8*)SvPVX(transv);
            tlen = SvCUR(transv);
            tend = t + tlen;
+           Safefree(cp);
        }
        else if (!rlen && !del) {
            r = t; rlen = tlen; rend = tend;
        }
        if (!squash) {
-               if (t == r ||
+               if ((!rlen && !del) || t == r ||
                    (tlen == rlen && memEQ((char *)t, (char *)r, tlen)))
                {
                    o->op_private |= OPpTRANS_IDENTICAL;
@@ -2743,11 +2748,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        while (t < tend || tfirst <= tlast) {
            /* see if we need more "t" chars */
            if (tfirst > tlast) {
-               tfirst = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
+               tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0);
                t += ulen;
-               if (t < tend && *t == 0xff) {   /* illegal utf8 val indicates range */
+               if (t < tend && NATIVE_TO_UTF(*t) == 0xff) {    /* illegal utf8 val indicates range */
                    t++;
-                   tlast = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
+                   tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0);
                    t += ulen;
                }
                else
@@ -2757,11 +2762,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            /* now see if we need more "r" chars */
            if (rfirst > rlast) {
                if (r < rend) {
-                   rfirst = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
+                   rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0);
                    r += ulen;
-                   if (r < rend && *r == 0xff) {       /* illegal utf8 val indicates range */
+                   if (r < rend && NATIVE_TO_UTF(*r) == 0xff) {        /* illegal utf8 val indicates range */
                        r++;
-                       rlast = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
+                       rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0);
                        r += ulen;
                    }
                    else
@@ -2802,9 +2807,10 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
 
                if (rfirst + diff > max)
                    max = rfirst + diff;
-               rfirst += diff + 1;
                if (!grows)
-                   grows = (UNISKIP(tfirst) < UNISKIP(rfirst));
+                   grows = (tfirst < rfirst &&
+                            UNISKIP(tfirst) < UNISKIP(rfirst + diff));
+               rfirst += diff + 1;
            }
            tfirst += diff + 1;
        }
@@ -2820,12 +2826,13 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        else
            bits = 8;
 
+       Safefree(cPVOPo->op_pv);
        cSVOPo->op_sv = (SV*)swash_init("utf8", "", listsv, bits, none);
        SvREFCNT_dec(listsv);
        if (transv)
            SvREFCNT_dec(transv);
 
-       if (!del && havefinal)
+       if (!del && havefinal && rlen)
            (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
                           newSVuv((UV)final), 0);
 
@@ -2864,6 +2871,20 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
                }
            }
        }
+       if (!del) {
+           if (!rlen) {
+               j = rlen;
+               if (!squash)
+                   o->op_private |= OPpTRANS_IDENTICAL;
+           }
+           else if (j >= rlen)
+               j = rlen - 1;
+           else
+               cPVOPo->op_pv = (char*)Renew(tbl, 0x101+rlen-j, short);
+           tbl[0x100] = rlen - j;
+           for (i=0; i < rlen - j; i++)
+               tbl[0x101+i] = r[j+i];
+       }
     }
     else {
        if (!rlen && !del) {
@@ -2918,6 +2939,7 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
     if (type != OP_TRANS && PL_curstash) {
        pmop->op_pmnext = HvPMROOT(PL_curstash);
        HvPMROOT(PL_curstash) = pmop;
+       PmopSTASH_set(pmop,PL_curstash);
     }
 
     return (OP*)pmop;
@@ -3263,6 +3285,20 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg)
     PL_expect = XSTATE;
 }
 
+/*
+=for apidoc load_module
+
+Loads the module whose name is pointed to by the string part of name.
+Note that the actual module name, not its filename, should be given.
+Eg, "Foo::Bar" instead of "Foo/Bar.pm".  flags can be any of
+PERL_LOADMOD_DENY, PERL_LOADMOD_NOIMPORT, or PERL_LOADMOD_IMPORT_OPS
+(or 0 for no flags). ver, if specified, provides version semantics
+similar to C<use Foo::Bar VERSION>.  The optional trailing SV*
+arguments can be used to specify arguments to the module's import()
+method, similar to C<use Foo::Bar VERSION LIST>.
+
+=cut */
+
 void
 Perl_load_module(pTHX_ U32 flags, SV *name, SV *ver, ...)
 {
@@ -3558,7 +3594,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_BYTE);
+    cop->op_private = (PL_hints & HINT_PRIVATE_MASK);
 #ifdef NATIVE_HINTS
     cop->op_private |= NATIVE_HINTS;
 #endif
@@ -4064,7 +4100,7 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo
 
        op_free(expr);
        expr = (OP*)(listop);
-        null(expr);
+        op_null(expr);
        iterflags |= OPf_STACKED;
     }
     else {
@@ -4141,16 +4177,19 @@ Perl_cv_undef(pTHX_ CV *cv)
        SAVEVPTR(PL_curpad);
        PL_curpad = 0;
 
-       if (!CvCLONED(cv))
-           op_free(CvROOT(cv));
+       op_free(CvROOT(cv));
        CvROOT(cv) = Nullop;
        LEAVE;
     }
     SvPOK_off((SV*)cv);                /* forget prototype */
-    CvFLAGS(cv) = 0;
-    SvREFCNT_dec(CvGV(cv));
     CvGV(cv) = Nullgv;
-    SvREFCNT_dec(CvOUTSIDE(cv));
+    /* Since closure prototypes have the same lifetime as the containing
+     * CV, they don't hold a refcount on the outside CV.  This avoids
+     * the refcount loop between the outer CV (which keeps a refcount to
+     * the closure prototype in the pad entry for pp_anoncode()) and the
+     * closure prototype, and the ensuing memory leak.  --GSAR */
+    if (!CvANON(cv) || CvCLONED(cv))
+       SvREFCNT_dec(CvOUTSIDE(cv));
     CvOUTSIDE(cv) = Nullcv;
     if (CvCONST(cv)) {
        SvREFCNT_dec((SV*)CvXSUBANY(cv).any_ptr);
@@ -4177,8 +4216,13 @@ Perl_cv_undef(pTHX_ CV *cv)
        }
        CvPADLIST(cv) = Nullav;
     }
+    if (CvXSUB(cv)) {
+        CvXSUB(cv) = 0;
+    }
+    CvFLAGS(cv) = 0;
 }
 
+#ifdef DEBUG_CLOSURES
 STATIC void
 S_cv_dump(pTHX_ CV *cv)
 {
@@ -4225,6 +4269,7 @@ S_cv_dump(pTHX_ CV *cv)
     }
 #endif /* DEBUGGING */
 }
+#endif /* DEBUG_CLOSURES */
 
 STATIC CV *
 S_cv_clone2(pTHX_ CV *proto, CV *outside)
@@ -4259,9 +4304,9 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside)
     CvOWNER(cv)                = 0;
 #endif /* USE_THREADS */
     CvFILE(cv)         = CvFILE(proto);
-    CvGV(cv)           = (GV*)SvREFCNT_inc(CvGV(proto));
+    CvGV(cv)           = CvGV(proto);
     CvSTASH(cv)                = CvSTASH(proto);
-    CvROOT(cv)         = CvROOT(proto);
+    CvROOT(cv)         = OpREFCNT_inc(CvROOT(proto));
     CvSTART(cv)                = CvSTART(proto);
     if (outside)
        CvOUTSIDE(cv)   = (CV*)SvREFCNT_inc(outside);
@@ -4547,6 +4592,12 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 
     cv = (!name || GvCVGEN(gv)) ? Nullcv : GvCV(gv);
 
+#ifdef GV_SHARED_CHECK
+    if (cv && GvSHARED(gv) && SvREADONLY(cv)) {
+        Perl_croak(aTHX_ "Can't define subroutine %s (GV is shared)", name);
+    }
+#endif
+
     if (!block || !ps || *ps || attrs)
        const_sv = Nullsv;
     else
@@ -4554,6 +4605,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 
     if (cv) {
         bool exists = CvROOT(cv) || CvXSUB(cv);
+
+#ifdef GV_SHARED_CHECK
+        if (exists && GvSHARED(gv)) {
+            Perl_croak(aTHX_ "Can't redefine shared subroutine %s", name);
+        }
+#endif
+
         /* if the subroutine doesn't exist and wasn't pre-declared
          * with a prototype, assume it will be AUTOLOADed,
          * skipping the prototype check
@@ -4644,8 +4702,30 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        CvOUTSIDE(PL_compcv) = 0;
        CvPADLIST(cv) = CvPADLIST(PL_compcv);
        CvPADLIST(PL_compcv) = 0;
-       if (SvREFCNT(PL_compcv) > 1) /* XXX Make closures transit through stub. */
-           CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc((SV*)cv);
+       /* inner references to PL_compcv must be fixed up ... */
+       {
+           AV *padlist = CvPADLIST(cv);
+           AV *comppad_name = (AV*)AvARRAY(padlist)[0];
+           AV *comppad = (AV*)AvARRAY(padlist)[1];
+           SV **namepad = AvARRAY(comppad_name);
+           SV **curpad = AvARRAY(comppad);
+           for (ix = AvFILLp(comppad_name); ix > 0; ix--) {
+               SV *namesv = namepad[ix];
+               if (namesv && namesv != &PL_sv_undef
+                   && *SvPVX(namesv) == '&')
+               {
+                   CV *innercv = (CV*)curpad[ix];
+                   if (CvOUTSIDE(innercv) == PL_compcv) {
+                       CvOUTSIDE(innercv) = cv;
+                       if (!CvANON(innercv) || CvCLONED(innercv)) {
+                           (void)SvREFCNT_inc(cv);
+                           SvREFCNT_dec(PL_compcv);
+                       }
+                   }
+               }
+           }
+       }
+       /* ... before we throw it away */
        SvREFCNT_dec(PL_compcv);
     }
     else {
@@ -4656,7 +4736,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            PL_sub_generation++;
        }
     }
-    CvGV(cv) = (GV*)SvREFCNT_inc(gv);
+    CvGV(cv) = gv;
     CvFILE(cv) = CopFILE(PL_curcop);
     CvSTASH(cv) = PL_curstash;
 #ifdef USE_THREADS
@@ -4748,6 +4828,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        }
     }
 
+    /* If a potential closure prototype, don't keep a refcount on outer CV.
+     * This is okay as the lifetime of the prototype is tied to the
+     * lifetime of the outer CV.  Avoids memory leak due to reference
+     * loop. --GSAR */
+    if (!name)
+       SvREFCNT_dec(CvOUTSIDE(cv));
+
     if (name || aname) {
        char *s;
        char *tname = (name ? name : aname);
@@ -4932,7 +5019,7 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
            PL_sub_generation++;
        }
     }
-    CvGV(cv) = (GV*)SvREFCNT_inc(gv);
+    CvGV(cv) = gv;
 #ifdef USE_THREADS
     New(666, CvMUTEXP(cv), 1, perl_mutex);
     MUTEX_INIT(CvMUTEXP(cv));
@@ -5005,6 +5092,11 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
     else
        name = "STDOUT";
     gv = gv_fetchpv(name,TRUE, SVt_PVFM);
+#ifdef GV_SHARED_CHECK
+    if (GvSHARED(gv)) {
+        Perl_croak(aTHX_ "Bad symbol for form (GV is shared)");
+    }
+#endif
     GvMULTI_on(gv);
     if ((cv = GvFORM(gv))) {
        if (ckWARN(WARN_REDEFINE)) {
@@ -5018,7 +5110,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
     }
     cv = PL_compcv;
     GvFORM(gv) = cv;
-    CvGV(cv) = (GV*)SvREFCNT_inc(gv);
+    CvGV(cv) = gv;
     CvFILE(cv) = CopFILE(PL_curcop);
 
     for (ix = AvFILLp(PL_comppad); ix > 0; ix--) {
@@ -5121,6 +5213,11 @@ Perl_newAVREF(pTHX_ OP *o)
        o->op_ppaddr = PL_ppaddr[OP_PADAV];
        return o;
     }
+    else if ((o->op_type == OP_RV2AV || o->op_type == OP_PADAV)
+               && ckWARN(WARN_DEPRECATED)) {
+       Perl_warner(aTHX_ WARN_DEPRECATED,
+               "Using an array as a reference is deprecated");
+    }
     return newUNOP(OP_RV2AV, 0, scalar(o));
 }
 
@@ -5140,6 +5237,11 @@ Perl_newHVREF(pTHX_ OP *o)
        o->op_ppaddr = PL_ppaddr[OP_PADHV];
        return o;
     }
+    else if ((o->op_type == OP_RV2HV || o->op_type == OP_PADHV)
+               && ckWARN(WARN_DEPRECATED)) {
+       Perl_warner(aTHX_ WARN_DEPRECATED,
+               "Using a hash as a reference is deprecated");
+    }
     return newUNOP(OP_RV2HV, 0, scalar(o));
 }
 
@@ -5257,7 +5359,7 @@ Perl_ck_delete(pTHX_ OP *o)
            Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element or slice",
                  PL_op_desc[o->op_type]);
        }
-       null(kid);
+       op_null(kid);
     }
     return o;
 }
@@ -5287,7 +5389,7 @@ Perl_ck_eval(pTHX_ OP *o)
 
        if (!kid) {
            o->op_flags &= ~OPf_KIDS;
-           null(o);
+           op_null(o);
        }
        else if (kid->op_type == OP_LINESEQ) {
            LOGOP *enter;
@@ -5343,7 +5445,7 @@ Perl_ck_exec(pTHX_ OP *o)
        o = ck_fun(o);
        kid = cUNOPo->op_first->op_sibling;
        if (kid->op_type == OP_RV2GV)
-           null(kid);
+           op_null(kid);
     }
     else
        o = listkids(o);
@@ -5368,7 +5470,7 @@ Perl_ck_exists(pTHX_ OP *o)
        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);
+       op_null(kid);
     }
     return o;
 }
@@ -5583,6 +5685,12 @@ Perl_ck_fun(pTHX_ OP *o)
                    list(kid);
                break;
            case OA_AVREF:
+               if ((type == OP_PUSH || type == OP_UNSHIFT)
+                   && !kid->op_sibling && ckWARN(WARN_SYNTAX))
+                   Perl_warner(aTHX_ WARN_SYNTAX,
+                       "Useless use of %s with no values",
+                       PL_op_desc[type]);
+                   
                if (kid->op_type == OP_CONST &&
                    (kid->op_private & OPpCONST_BARE))
                {
@@ -5746,11 +5854,15 @@ Perl_ck_glob(pTHX_ OP *o)
 #if !defined(PERL_EXTERNAL_GLOB)
     /* XXX this can be tightened up and made more failsafe. */
     if (!gv) {
+       GV *glob_gv;
        ENTER;
-       Perl_load_module(aTHX_ 0, newSVpvn("File::Glob", 10), Nullsv,
-                        /* null-terminated import list */
-                        newSVpvn(":globally", 9), Nullsv);
+       Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvn("File::Glob", 10), Nullsv,
+                        Nullsv, Nullsv);
        gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
+       glob_gv = gv_fetchpv("File::Glob::csh_glob", FALSE, SVt_PVCV);
+       GvCV(gv) = GvCV(glob_gv);
+       SvREFCNT_inc((SV*)GvCV(gv));
+       GvIMPORTED_CV_on(gv);
        LEAVE;
     }
 #endif /* PERL_EXTERNAL_GLOB */
@@ -6193,7 +6305,7 @@ Perl_ck_sort(pTHX_ OP *o)
            }
            else if (kid->op_type == OP_LEAVE) {
                if (o->op_type == OP_SORT) {
-                   null(kid);                  /* wipe out leave */
+                   op_null(kid);                       /* wipe out leave */
                    kid->op_next = kid;
 
                    for (k = kLISTOP->op_first->op_next; k; k = k->op_next) {
@@ -6224,7 +6336,7 @@ Perl_ck_sort(pTHX_ OP *o)
            o->op_flags |= OPf_SPECIAL;
        }
        else if (kid->op_type == OP_RV2SV || kid->op_type == OP_PADSV)
-           null(firstkid);
+           op_null(firstkid);
 
        firstkid = firstkid->op_sibling;
     }
@@ -6387,7 +6499,7 @@ Perl_ck_subr(pTHX_ OP *o)
     if (cvop->op_type == OP_RV2CV) {
        SVOP* tmpop;
        o->op_private |= (cvop->op_private & OPpENTERSUB_AMPER);
-       null(cvop);             /* disable rv2cv */
+       op_null(cvop);          /* disable rv2cv */
        tmpop = (SVOP*)((UNOP*)cvop)->op_first;
        if (tmpop->op_type == OP_GV && !(o->op_private & OPpENTERSUB_AMPER)) {
            GV *gv = cGVOPx_gv(tmpop);
@@ -6649,7 +6761,7 @@ Perl_peep(pTHX_ register OP *o)
                        o->op_private |= OPpTARGET_MY;
                    }
                }
-               null(o->op_next);
+               op_null(o->op_next);
            }
          ignore_optimization:
            o->op_seq = PL_op_seqmax++;
@@ -6682,7 +6794,7 @@ Perl_peep(pTHX_ register OP *o)
        case OP_GV:
            if (o->op_next->op_type == OP_RV2SV) {
                if (!(o->op_next->op_private & OPpDEREF)) {
-                   null(o->op_next);
+                   op_null(o->op_next);
                    o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO
                                                               | OPpOUR_INTRO);
                    o->op_next = o->op_next->op_next;
@@ -6698,14 +6810,14 @@ Perl_peep(pTHX_ register OP *o)
                    pop->op_next->op_type == OP_AELEM &&
                    !(pop->op_next->op_private &
                      (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)) &&
-                   (i = SvIV(((SVOP*)pop)->op_sv) - PL_compiling.cop_arybase)
+                   (i = SvIV(((SVOP*)pop)->op_sv) - PL_curcop->cop_arybase)
                                <= 255 &&
                    i >= 0)
                {
                    GV *gv;
-                   null(o->op_next);
-                   null(pop->op_next);
-                   null(pop);
+                   op_null(o->op_next);
+                   op_null(pop->op_next);
+                   op_null(pop);
                    o->op_flags |= pop->op_next->op_flags & OPf_MOD;
                    o->op_next = pop->op_next->op_next;
                    o->op_type = OP_AELEMFAST;
@@ -6745,6 +6857,7 @@ Perl_peep(pTHX_ register OP *o)
            break;
 
        case OP_ENTERLOOP:
+       case OP_ENTERITER:
            o->op_seq = PL_op_seqmax++;
            while (cLOOP->op_redoop->op_type == OP_NULL)
                cLOOP->op_redoop = cLOOP->op_redoop->op_next;
@@ -6761,7 +6874,7 @@ Perl_peep(pTHX_ register OP *o)
        case OP_MATCH:
        case OP_SUBST:
            o->op_seq = PL_op_seqmax++;
-           while (cPMOP->op_pmreplstart && 
+           while (cPMOP->op_pmreplstart &&
                   cPMOP->op_pmreplstart->op_type == OP_NULL)
                cPMOP->op_pmreplstart = cPMOP->op_pmreplstart->op_next;
            peep(cPMOP->op_pmreplstart);
@@ -6930,7 +7043,14 @@ static void
 const_sv_xsub(pTHXo_ CV* cv)
 {
     dXSARGS;
+    if (items != 0) {
+#if 0
+        Perl_croak(aTHX_ "usage: %s::%s()",
+                   HvNAME(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv)));
+#endif
+    }
     EXTEND(sp, 1);
     ST(0) = (SV*)XSANY.any_ptr;
     XSRETURN(1);
 }
+