This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
doc tweaks suggested by Abigail, M.J.T. Guy, and Larry Wall
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 3440b1c..ab7a056 100644 (file)
--- a/op.c
+++ b/op.c
@@ -782,6 +782,10 @@ scalarvoid(OP *o)
     case OP_REPEAT:
        if (o->op_flags & OPf_STACKED)
            break;
+       goto func_ops;
+    case OP_SUBSTR:
+       if (o->op_private == 4)
+           break;
        /* FALL THROUGH */
     case OP_GVSV:
     case OP_WANTARRAY:
@@ -798,7 +802,6 @@ scalarvoid(OP *o)
     case OP_HEX:
     case OP_OCT:
     case OP_LENGTH:
-    case OP_SUBSTR:
     case OP_VEC:
     case OP_INDEX:
     case OP_RINDEX:
@@ -851,6 +854,7 @@ scalarvoid(OP *o)
     case OP_GGRNAM:
     case OP_GGRGID:
     case OP_GETLOGIN:
+      func_ops:
        if (!(o->op_private & OPpLVAL_INTRO))
            useless = op_desc[o->op_type];
        break;
@@ -1206,10 +1210,14 @@ mod(OP *o, I32 type)
     case OP_KEYS:
        if (type != OP_SASSIGN)
            goto nomod;
+       goto lvalue_func;
+    case OP_SUBSTR:
+       if (o->op_private == 4) /* don't allow 4 arg substr as lvalue */
+           goto nomod;
        /* FALL THROUGH */
     case OP_POS:
     case OP_VEC:
-    case OP_SUBSTR:
+      lvalue_func:
        pad_free(o->op_targ);
        o->op_targ = pad_alloc(o->op_type, SVs_PADMY);
        assert(SvTYPE(PAD_SV(o->op_targ)) == SVt_NULL);
@@ -1296,6 +1304,9 @@ scalar_mod_type(OP *o, I32 type)
     case OP_CONCAT:
     case OP_SUBST:
     case OP_TRANS:
+    case OP_READ:
+    case OP_SYSREAD:
+    case OP_RECV:
     case OP_ANDASSIGN: /* may work later */
     case OP_ORASSIGN:  /* may work later */
        return TRUE;
@@ -1510,11 +1521,21 @@ scope(OP *o)
     return o;
 }
 
+void
+save_hints(void)
+{
+    SAVEI32(hints);
+    SAVESPTR(GvHV(hintgv));
+    GvHV(hintgv) = newHVhv(GvHV(hintgv));
+    SAVEFREESV(GvHV(hintgv));
+}
+
 int
 block_start(int full)
 {
     dTHR;
     int retval = savestack_ix;
+
     SAVEI32(comppad_name_floor);
     if (full) {
        if ((comppad_name_fill = AvFILLp(comppad_name)) > 0)
@@ -1529,7 +1550,7 @@ block_start(int full)
     SAVEI32(padix_floor);
     padix_floor = padix;
     pad_reset_pending = FALSE;
-    SAVEI32(hints);
+    SAVEHINTS();
     hints &= ~HINT_BLOCK_SCOPE;
     return retval;
 }
@@ -2082,8 +2103,11 @@ newPMOP(I32 type, I32 flags)
     pmop->op_flags = flags;
     pmop->op_private = 0 | (flags >> 8);
 
+    if (hints & HINT_RE_TAINT)
+       pmop->op_pmpermflags |= PMf_RETAINT;
     if (hints & HINT_LOCALE)
-       pmop->op_pmpermflags = (pmop->op_pmflags |= PMf_LOCALE);
+       pmop->op_pmpermflags |= PMf_LOCALE;
+    pmop->op_pmflags = pmop->op_pmpermflags;
 
     /* link into pm list */
     if (type != OP_TRANS && curstash) {
@@ -2168,7 +2192,7 @@ pmruntime(OP *o, OP *expr, OP *repl)
 #ifdef USE_THREADS
                    if (curop->op_type == OP_THREADSV) {
                        repl_has_vars = 1;
-                       if (strchr("&`'123456789+", curop->op_private)) {
+                       if (strchr("&`'123456789+", curop->op_private))
                            break;
                    }
 #else
@@ -3024,12 +3048,44 @@ newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont
 #endif
     }
     if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
-       expr = scalar(ref(expr, OP_ITER));
+       expr = mod(force_list(scalar(ref(expr, OP_ITER))), OP_GREPSTART);
        iterflags |= OPf_STACKED;
     }
+    else if (expr->op_type == OP_NULL &&
+             (expr->op_flags & OPf_KIDS) &&
+             ((BINOP*)expr)->op_first->op_type == OP_FLOP)
+    {
+       /* Basically turn for($x..$y) into the same as for($x,$y), but we
+        * set the STACKED flag to indicate that these values are to be
+        * treated as min/max values by 'pp_iterinit'.
+        */
+       UNOP* flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first;
+       CONDOP* range = (CONDOP*) flip->op_first;
+       OP* left  = range->op_first;
+       OP* right = left->op_sibling;
+       LISTOP* listop;
+
+       range->op_flags &= ~OPf_KIDS;
+       range->op_first = Nullop;
+
+       listop = (LISTOP*)newLISTOP(OP_LIST, 0, left, right);
+       listop->op_first->op_next = range->op_true;
+       left->op_next = range->op_false;
+       right->op_next = (OP*)listop;
+       listop->op_next = listop->op_first;
+
+       op_free(expr);
+       expr = (OP*)(listop);
+        null(expr);
+       iterflags |= OPf_STACKED;
+    }
+    else {
+        expr = mod(force_list(expr), OP_GREPSTART);
+    }
+
+
     loop = (LOOP*)list(convert(OP_ENTERITER, iterflags,
-       append_elem(OP_LIST, mod(force_list(expr), OP_GREPSTART),
-                   scalar(sv))));
+                              append_elem(OP_LIST, expr, scalar(sv))));
     assert(!loop->op_next);
     Renew(loop, 1, LOOP);
     loop->op_targ = padoff;
@@ -3383,7 +3439,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
     GV *gv = gv_fetchpv(name ? name : "__ANON__",
                        GV_ADDMULTI | (block ? 0 : GV_NOINIT), SVt_PVCV);
     char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch;
-    register CV *cv;
+    register CV *cv=0;
     I32 ix;
 
     if (o)
@@ -3422,7 +3478,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
                goto done;
            }
            /* ahem, death to those who redefine active sort subs */
-           if (curstackinfo->si_type == SI_SORT && sortcop == CvSTART(cv))
+           if (curstackinfo->si_type == PERLSI_SORT && sortcop == CvSTART(cv))
                croak("Can't redefine active sort subroutine %s", name);
            if(const_sv = cv_const_sv(cv))
                const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv));
@@ -4921,7 +4977,7 @@ peep(register OP *o)
 
        case OP_PADAV:
            if (o->op_next->op_type == OP_RV2AV
-               && (o->op_next->op_flags && OPf_REF))
+               && (o->op_next->op_flags & OPf_REF))
            {
                null(o->op_next);
                o->op_next = o->op_next->op_next;
@@ -4930,7 +4986,7 @@ peep(register OP *o)
        
        case OP_PADHV:
            if (o->op_next->op_type == OP_RV2HV
-               && (o->op_next->op_flags && OPf_REF))
+               && (o->op_next->op_flags & OPf_REF))
            {
                null(o->op_next);
                o->op_next = o->op_next->op_next;