typo fix
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index 155c001..386e9de 100644 (file)
--- a/op.c
+++ b/op.c
 /* #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
@@ -152,11 +159,15 @@ Perl_pad_allocmy(pTHX_ char *name)
                && (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
                && strEQ(name, SvPVX(sv)))
            {
-               Perl_warner(aTHX_ WARN_UNSAFE,
+               if (PL_in_my != KEY_our
+                   || GvSTASH(sv) == (PL_curstash ? PL_curstash : PL_defstash))
+               {
+                   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"));
+               }
                break;
            }
        }
@@ -174,8 +185,11 @@ Perl_pad_allocmy(pTHX_ char *name)
        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 ? PL_curstash : 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 */
@@ -243,8 +257,11 @@ S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv,
                    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 */
+                   if (SvFLAGS(sv) & SVpad_OUR) { /* An "our" variable */
                        SvFLAGS(namesv) |= SVpad_OUR;
+                       (void)SvUPGRADE(namesv, SVt_PVGV);
+                       GvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)GvSTASH(sv));
+                   }
                    if (SvOBJECT(sv)) {         /* A typed var */
                        SvOBJECT_on(namesv);
                        (void)SvUPGRADE(namesv, SVt_PVMG);
@@ -505,8 +522,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 +681,6 @@ Perl_op_free(pTHX_ OP *o)
                OP_REFCNT_UNLOCK;
                return;
            }
-           o->op_targ = 0;             /* XXXXXX */
            OP_REFCNT_UNLOCK;
            break;
        default:
@@ -1064,7 +1084,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;
@@ -1671,7 +1691,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,6 +1840,7 @@ 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 &&
@@ -2230,6 +2251,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;
@@ -4127,9 +4149,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;
 }
 
@@ -4910,11 +4932,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 +5033,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;
@@ -5370,7 +5413,7 @@ Perl_ck_glob(pTHX_ OP *o)
     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));
@@ -5381,7 +5424,7 @@ Perl_ck_glob(pTHX_ OP *o)
        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,
@@ -5587,31 +5630,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. */
@@ -6195,26 +6213,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;