fh.t typo
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index cdc9332..412eb57 100644 (file)
--- a/op.c
+++ b/op.c
@@ -51,14 +51,17 @@ static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
        CV* startcv, I32 cx_ix, I32 saweval));
 static OP *newDEFSVOP _((void));
 static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
+static void simplify_sort _((OP *o));
+static bool is_handle_constructor _((OP *o, I32 argnum));
 #endif
 
 STATIC char*
 gv_ename(GV *gv)
 {
+    STRLEN n_a;
     SV* tmpsv = sv_newmortal();
     gv_efullname3(tmpsv, gv, Nullch);
-    return SvPV(tmpsv,PL_na);
+    return SvPV(tmpsv,n_a);
 }
 
 STATIC OP *
@@ -549,11 +552,15 @@ find_threadsv(char *name)
     if (!p)
        return NOT_IN_PAD;
     key = p - PL_threadsv_names;
+    MUTEX_LOCK(&thr->mutex);
     svp = av_fetch(thr->threadsv, key, FALSE);
-    if (!svp) {
+    if (svp)
+       MUTEX_UNLOCK(&thr->mutex);
+    else {
        SV *sv = NEWSV(0, 0);
        av_store(thr->threadsv, key, sv);
        thr->threadsvp = AvARRAY(thr->threadsv);
+       MUTEX_UNLOCK(&thr->mutex);
        /*
         * Some magic variables used to be automagically initialised
         * in gv_fetchpv. Those which are now per-thread magicals get
@@ -570,6 +577,16 @@ find_threadsv(char *name)
        case '`':
        case '\'':
            PL_sawampersand = TRUE;
+           /* FALL THROUGH */
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
            SvREADONLY_on(sv);
            /* FALL THROUGH */
 
@@ -812,7 +829,8 @@ scalarvoid(OP *o)
     SV* sv;
 
     /* assumes no premature commitment */
-    if (!o || (o->op_flags & OPf_WANT) == OPf_WANT_LIST || PL_error_count
+    U8 want = o->op_flags & OPf_WANT;
+    if (!o || (want && want != OPf_WANT_SCALAR) || PL_error_count
         || o->op_type == OP_RETURN)
        return o;
 
@@ -1120,6 +1138,7 @@ mod(OP *o, I32 type)
     dTHR;
     OP *kid;
     SV *sv;
+    STRLEN n_a;
 
     if (!o || PL_error_count)
        return o;
@@ -1247,7 +1266,7 @@ mod(OP *o, I32 type)
        PL_modcount++;
        if (!type)
            croak("Can't localize lexical variable %s",
-               SvPV(*av_fetch(PL_comppad_name, o->op_targ, 4), PL_na));
+               SvPV(*av_fetch(PL_comppad_name, o->op_targ, 4), n_a));
        break;
 
 #ifdef USE_THREADS
@@ -1369,6 +1388,28 @@ scalar_mod_type(OP *o, I32 type)
     }
 }
 
+STATIC bool
+is_handle_constructor(OP *o, I32 argnum)
+{
+    switch (o->op_type) {
+    case OP_PIPE_OP:
+    case OP_SOCKPAIR:
+       if (argnum == 2)
+           return TRUE;
+       /* FALL THROUGH */
+    case OP_SYSOPEN:
+    case OP_OPEN:
+    case OP_SOCKET:
+    case OP_OPEN_DIR:
+    case OP_ACCEPT:
+       if (argnum == 1)
+           return TRUE;
+       /* FALL THROUGH */
+    default:
+       return FALSE;
+    }
+}
+
 OP *
 refkids(OP *o, I32 type)
 {
@@ -1405,6 +1446,8 @@ ref(OP *o, I32 type)
            ref(kid, type);
        break;
     case OP_RV2SV:
+       if (type == OP_DEFINED)
+           o->op_flags |= OPf_SPECIAL;         /* don't create GV */
        ref(cUNOPo->op_first, o->op_type);
        /* FALL THROUGH */
     case OP_PADSV:
@@ -1425,6 +1468,8 @@ ref(OP *o, I32 type)
        o->op_flags |= OPf_REF;
        /* FALL THROUGH */
     case OP_RV2GV:
+       if (type == OP_DEFINED)
+           o->op_flags |= OPf_SPECIAL;         /* don't create GV */
        ref(cUNOPo->op_first, o->op_type);
        break;
 
@@ -1693,7 +1738,7 @@ localize(OP *o, I32 lex)
            char *s;
            for (s = PL_bufptr; *s && (isALNUM(*s) || (*s & 0x80) || strchr("@$%, ",*s)); s++) ;
            if (*s == ';' || *s == '=')
-               warner(WARN_PARENTHESIS, "Parens missing around \"%s\" list",
+               warner(WARN_PARENTHESIS, "Parentheses missing around \"%s\" list",
                                lex ? "my" : "local");
        }
     }
@@ -3420,13 +3465,15 @@ newLOOPEX(I32 type, OP *label)
 {
     dTHR;
     OP *o;
+    STRLEN n_a;
+
     if (type != OP_GOTO || label->op_type == OP_CONST) {
        /* "last()" means "last" */
        if (label->op_type == OP_STUB && (label->op_flags & OPf_PARENS))
            o = newOP(type, OPf_SPECIAL);
        else {
            o = newPVOP(type, 0, savepv(label->op_type == OP_CONST
-                                       ? SvPVx(((SVOP*)label)->op_sv, PL_na)
+                                       ? SvPVx(((SVOP*)label)->op_sv, n_a)
                                        : ""));
        }
        op_free(label);
@@ -3680,7 +3727,11 @@ cv_clone2(CV *proto, CV *outside)
 CV *
 cv_clone(CV *proto)
 {
-    return cv_clone2(proto, CvOUTSIDE(proto));
+    CV *cv;
+    MUTEX_LOCK(&PL_cred_mutex);                /* XXX create separate mutex */
+    cv = cv_clone2(proto, CvOUTSIDE(proto));
+    MUTEX_UNLOCK(&PL_cred_mutex);      /* XXX create separate mutex */
+    return cv;
 }
 
 void
@@ -3756,10 +3807,11 @@ CV *
 newSUB(I32 floor, OP *o, OP *proto, OP *block)
 {
     dTHR;
-    char *name = o ? SvPVx(cSVOPo->op_sv, PL_na) : Nullch;
+    STRLEN n_a;
+    char *name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
     GV *gv = gv_fetchpv(name ? name : "__ANON__",
                        GV_ADDMULTI | (block ? 0 : GV_NOINIT), SVt_PVCV);
-    char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, PL_na) : Nullch;
+    char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch;
     register CV *cv=0;
     I32 ix;
 
@@ -3866,7 +3918,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
                else {
                    /* force display of errors found but not reported */
                    sv_catpv(ERRSV, not_safe);
-                   croak("%s", SvPVx(ERRSV, PL_na));
+                   croak("%s", SvPVx(ERRSV, n_a));
                }
            }
        }
@@ -3992,6 +4044,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
     return cv;
 }
 
+/* XXX unsafe for threads if eval_owner isn't held */
 void
 newCONSTSUB(HV *stash, char *name, SV *sv)
 {
@@ -4108,9 +4161,10 @@ newFORM(I32 floor, OP *o, OP *block)
     char *name;
     GV *gv;
     I32 ix;
+    STRLEN n_a;
 
     if (o)
-       name = SvPVx(cSVOPo->op_sv, PL_na);
+       name = SvPVx(cSVOPo->op_sv, n_a);
     else
        name = "STDOUT";
     gv = gv_fetchpv(name,TRUE, SVt_PVFM);
@@ -4459,6 +4513,7 @@ ck_rvconst(register OP *o)
        int iscv;
        GV *gv;
        SV *kidsv = kid->op_sv;
+       STRLEN n_a;
 
        /* Is it a constant from cv_const_sv()? */
        if (SvROK(kidsv) && SvREADONLY(kidsv)) {
@@ -4497,7 +4552,7 @@ ck_rvconst(register OP *o)
                croak("Constant is not %s reference", badtype);
            return o;
        }
-       name = SvPV(kidsv, PL_na);
+       name = SvPV(kidsv, n_a);
        if ((PL_hints & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) {
            char *badthing = Nullch;
            switch (o->op_type) {
@@ -4560,8 +4615,9 @@ ck_ftst(OP *o)
        SVOP *kid = (SVOP*)cUNOPo->op_first;
 
        if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) {
+           STRLEN n_a;
            OP *newop = newGVOP(type, OPf_REF,
-               gv_fetchpv(SvPVx(kid->op_sv, PL_na), TRUE, SVt_PVIO));
+               gv_fetchpv(SvPVx(kid->op_sv, n_a), TRUE, SVt_PVIO));
            op_free(o);
            return newop;
        }
@@ -4596,6 +4652,7 @@ ck_fun(OP *o)
     }
 
     if (o->op_flags & OPf_KIDS) {
+       STRLEN n_a;
        tokid = &cLISTOPo->op_first;
        kid = cLISTOPo->op_first;
        if (kid->op_type == OP_PUSHMARK ||
@@ -4612,6 +4669,12 @@ ck_fun(OP *o)
            sibl = kid->op_sibling;
            switch (oa & 7) {
            case OA_SCALAR:
+               /* list seen where single (scalar) arg expected? */
+               if (numargs == 1 && !(oa >> 4)
+                   && kid->op_type == OP_LIST && type != OP_SCALAR)
+               {
+                   return too_many_arguments(o,PL_op_desc[type]);
+               }
                scalar(kid);
                break;
            case OA_LIST:
@@ -4624,8 +4687,9 @@ ck_fun(OP *o)
                break;
            case OA_AVREF:
                if (kid->op_type == OP_CONST &&
-                 (kid->op_private & OPpCONST_BARE)) {
-                   char *name = SvPVx(((SVOP*)kid)->op_sv, PL_na);
+                   (kid->op_private & OPpCONST_BARE))
+               {
+                   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))
@@ -4638,13 +4702,14 @@ ck_fun(OP *o)
                    *tokid = kid;
                }
                else if (kid->op_type != OP_RV2AV && kid->op_type != OP_PADAV)
-                   bad_type(numargs, "array", PL_op_desc[o->op_type], kid);
+                   bad_type(numargs, "array", PL_op_desc[type], kid);
                mod(kid, type);
                break;
            case OA_HVREF:
                if (kid->op_type == OP_CONST &&
-                 (kid->op_private & OPpCONST_BARE)) {
-                   char *name = SvPVx(((SVOP*)kid)->op_sv, PL_na);
+                   (kid->op_private & OPpCONST_BARE))
+               {
+                   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))
@@ -4657,7 +4722,7 @@ ck_fun(OP *o)
                    *tokid = kid;
                }
                else if (kid->op_type != OP_RV2HV && kid->op_type != OP_PADHV)
-                   bad_type(numargs, "hash", PL_op_desc[o->op_type], kid);
+                   bad_type(numargs, "hash", PL_op_desc[type], kid);
                mod(kid, type);
                break;
            case OA_CVREF:
@@ -4674,9 +4739,10 @@ ck_fun(OP *o)
            case OA_FILEREF:
                if (kid->op_type != OP_GV && kid->op_type != OP_RV2GV) {
                    if (kid->op_type == OP_CONST &&
-                     (kid->op_private & OPpCONST_BARE)) {
+                       (kid->op_private & OPpCONST_BARE))
+                   {
                        OP *newop = newGVOP(OP_GV, 0,
-                           gv_fetchpv(SvPVx(((SVOP*)kid)->op_sv, PL_na), TRUE,
+                           gv_fetchpv(SvPVx(((SVOP*)kid)->op_sv, n_a), TRUE,
                                        SVt_PVIO) );
                        op_free(kid);
                        kid = newop;
@@ -4686,8 +4752,12 @@ ck_fun(OP *o)
                        bad_type(numargs, "HANDLE", PL_op_desc[o->op_type], kid);
                    }
                    else {
+                       I32 flags = OPf_SPECIAL;
+                       /* is this op a FH constructor? */
+                       if (is_handle_constructor(o,numargs))
+                           flags = 0;
                        kid->op_sibling = 0;
-                       kid = newUNOP(OP_RV2GV, 0, scalar(kid));
+                       kid = newUNOP(OP_RV2GV, flags, scalar(kid));
                    }
                    kid->op_sibling = sibl;
                    *tokid = kid;
@@ -4733,10 +4803,8 @@ ck_glob(OP *o)
        gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
 
     if (gv && GvIMPORTED_CV(gv)) {
-       static int glob_index;
-
        append_elem(OP_GLOB, o,
-                   newSVOP(OP_CONST, 0, newSViv(glob_index++)));
+                   newSVOP(OP_CONST, 0, newSViv(PL_glob_index++)));
        o->op_type = OP_LIST;
        o->op_ppaddr = PL_ppaddr[OP_LIST];
        cLISTOPo->op_first->op_type = OP_PUSHMARK;
@@ -5019,7 +5087,9 @@ ck_sort(OP *o)
        o->op_private |= OPpLOCALE;
 #endif
 
-    if (o->op_flags & OPf_STACKED) {
+    if (o->op_flags & OPf_STACKED)
+       simplify_sort(o);
+    if (o->op_flags & OPf_STACKED) {                /* may have been cleared */
        OP *kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
        OP *k;
        kid = kUNOP->op_first;                          /* get past rv2gv */
@@ -5061,6 +5131,66 @@ ck_sort(OP *o)
     return o;
 }
 
+STATIC void
+simplify_sort(OP *o)
+{
+    dTHR;
+    register OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
+    OP *k;
+    int reversed;
+    if (!(o->op_flags & OPf_STACKED))
+       return;
+    kid = kUNOP->op_first;                             /* get past rv2gv */
+    if (kid->op_type != OP_SCOPE)
+       return;
+    kid = kLISTOP->op_last;                            /* get past scope */
+    switch(kid->op_type) {
+       case OP_NCMP:
+       case OP_I_NCMP:
+       case OP_SCMP:
+           break;
+       default:
+           return;
+    }
+    k = kid;                                           /* remember this node*/
+    if (kBINOP->op_first->op_type != OP_RV2SV)
+       return;
+    kid = kBINOP->op_first;                            /* get past cmp */
+    if (kUNOP->op_first->op_type != OP_GV)
+       return;
+    kid = kUNOP->op_first;                             /* get past rv2sv */
+    if (GvSTASH(kGVOP->op_gv) != PL_curstash)
+       return;
+    if (strEQ(GvNAME(kGVOP->op_gv), "a"))
+       reversed = 0;
+    else if(strEQ(GvNAME(kGVOP->op_gv), "b"))
+       reversed = 1;
+    else
+       return;
+    kid = k;                                           /* back to cmp */
+    if (kBINOP->op_last->op_type != OP_RV2SV)
+       return;
+    kid = kBINOP->op_last;                             /* down to 2nd arg */
+    if (kUNOP->op_first->op_type != OP_GV)
+       return;
+    kid = kUNOP->op_first;                             /* get past rv2sv */
+    if (GvSTASH(kGVOP->op_gv) != PL_curstash
+       || ( reversed
+           ? strNE(GvNAME(kGVOP->op_gv), "a")
+           : strNE(GvNAME(kGVOP->op_gv), "b")))
+       return;
+    o->op_flags &= ~(OPf_STACKED | OPf_SPECIAL);
+    if (reversed)
+       o->op_private |= OPpSORT_REVERSE;
+    if (k->op_type == OP_NCMP)
+       o->op_private |= OPpSORT_NUMERIC;
+    if (k->op_type == OP_I_NCMP)
+       o->op_private |= OPpSORT_NUMERIC | OPpSORT_INTEGER;
+    op_free(cLISTOPo->op_first->op_sibling);   /* delete comparison block */
+    cLISTOPo->op_first->op_sibling = cLISTOPo->op_last;
+    cLISTOPo->op_children = 1;
+}
+
 OP *
 ck_split(OP *o)
 {
@@ -5125,6 +5255,7 @@ ck_subr(OP *o)
     GV *namegv = 0;
     int optional = 0;
     I32 arg = 0;
+    STRLEN n_a;
 
     for (cvop = o2; cvop->op_sibling; cvop = cvop->op_sibling) ;
     if (cvop->op_type == OP_RV2CV) {
@@ -5136,7 +5267,7 @@ ck_subr(OP *o)
            cv = GvCVu(tmpop->op_sv);
            if (cv && SvPOK(cv) && !(o->op_private & OPpENTERSUB_AMPER)) {
                namegv = CvANON(cv) ? (GV*)tmpop->op_sv : CvGV(cv);
-               proto = SvPV((SV*)cv, PL_na);
+               proto = SvPV((SV*)cv, n_a);
            }
        }
     }
@@ -5228,7 +5359,7 @@ ck_subr(OP *o)
            default:
              oops:
                croak("Malformed prototype for %s: %s",
-                       gv_ename(namegv), SvPV((SV*)cv, PL_na));
+                       gv_ename(namegv), SvPV((SV*)cv, n_a));
            }
        }
        else
@@ -5272,6 +5403,8 @@ peep(register OP *o)
 {
     dTHR;
     register OP* oldop = 0;
+    STRLEN n_a;
+
     if (!o || o->op_seq)
        return;
     ENTER;
@@ -5434,7 +5567,7 @@ peep(register OP *o)
            indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
            if (!indsvp) {
                croak("No such field \"%s\" in variable %s of type %s",
-                     key, SvPV(lexname, PL_na), HvNAME(SvSTASH(lexname)));
+                     key, SvPV(lexname, n_a), HvNAME(SvSTASH(lexname)));
            }
            ind = SvIV(*indsvp);
            if (ind < 1)