This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regularise "given"
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 689f696..23f25db 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2489,7 +2489,7 @@ S_check_hash_fields_and_hekify(pTHX_ UNOP *rop, SVOP *key_op)
 /* info returned by S_sprintf_is_multiconcatable() */
 
 struct sprintf_ismc_info {
-    UV     nargs;     /* num of args to sprintf (not including the format) */
+    SSize_t nargs;    /* num of args to sprintf (not including the format) */
     char  *start;     /* start of raw format string */
     char  *end;       /* bytes after end of raw format string */
     STRLEN total_len; /* total length (in bytes) of format string, not
@@ -2517,7 +2517,7 @@ S_sprintf_is_multiconcatable(pTHX_ OP *o,struct sprintf_ismc_info *info)
     OP    *pm, *constop, *kid;
     SV    *sv;
     char  *s, *e, *p;
-    UV     nargs, nformats;
+    SSize_t nargs, nformats;
     STRLEN cur, total_len, variant;
     bool   utf8;
 
@@ -2552,7 +2552,7 @@ S_sprintf_is_multiconcatable(pTHX_ OP *o,struct sprintf_ismc_info *info)
     for (p = s; p < e; p++) {
         if (*p != '%') {
             total_len++;
-            if (UTF8_IS_INVARIANT(*p))
+            if (!UTF8_IS_INVARIANT(*p))
                 variant++;
             continue;
         }
@@ -2660,8 +2660,8 @@ S_maybe_multiconcat(pTHX_ OP *o)
         STRLEN len;   /* ... len set to SvPV(..., len) */
     } *argp, *toparg, args[PERL_MULTICONCAT_MAXARG*2 + 1];
 
-    UV nargs  = 0;
-    UV nconst = 0;
+    SSize_t nargs  = 0;
+    SSize_t nconst = 0;
     STRLEN variant;
     bool utf8 = FALSE;
     bool kid_is_last = FALSE; /* most args will be the RHS kid of a concat op;
@@ -3043,7 +3043,7 @@ S_maybe_multiconcat(pTHX_ OP *o)
                          + ((nargs + 1) * (variant ? 2 : 1))
                         )
                     );
-    const_str = (char *)PerlMemShared_malloc(total_len);
+    const_str = (char *)PerlMemShared_malloc(total_len ? total_len : 1);
 
     /* Extract all the non-const expressions from the concat tree then
      * dispose of the old tree, e.g. convert the tree from this:
@@ -3095,14 +3095,14 @@ S_maybe_multiconcat(pTHX_ OP *o)
             if (*p == '%') {
                 p++;
                 if (*p != '%') {
-                    (lenp++)->uv = q - oldq;
+                    (lenp++)->ssize = q - oldq;
                     oldq = q;
                     continue;
                 }
             }
             *q++ = *p;
         }
-        lenp->uv = q - oldq;
+        lenp->ssize = q - oldq;
         assert((STRLEN)(q - const_str) == total_len);
 
         /* Attach all the args (i.e. the kids of the sprintf) to o (which
@@ -3123,7 +3123,7 @@ S_maybe_multiconcat(pTHX_ OP *o)
         p = const_str;
         lenp = aux + PERL_MULTICONCAT_IX_LENGTHS;
 
-        lenp->size = -1;
+        lenp->ssize = -1;
 
         /* Concatenate all const strings into const_str.
          * Note that args[] contains the RHS args in reverse order, so
@@ -3133,15 +3133,15 @@ S_maybe_multiconcat(pTHX_ OP *o)
         for (argp = toparg; argp >= args; argp--) {
             if (!argp->p)
                 /* not a const op */
-                (++lenp)->size = -1;
+                (++lenp)->ssize = -1;
             else {
                 STRLEN l = argp->len;
                 Copy(argp->p, p, l, char);
                 p += l;
-                if (lenp->size == -1)
-                    lenp->size = l;
+                if (lenp->ssize == -1)
+                    lenp->ssize = l;
                 else
-                    lenp->size += l;
+                    lenp->ssize += l;
             }
         }
 
@@ -3215,11 +3215,11 @@ S_maybe_multiconcat(pTHX_ OP *o)
 
     /* Populate the aux struct */
 
-    aux[PERL_MULTICONCAT_IX_NARGS].uv       = nargs;
+    aux[PERL_MULTICONCAT_IX_NARGS].ssize     = nargs;
     aux[PERL_MULTICONCAT_IX_PLAIN_PV].pv    = utf8 ? NULL : const_str;
-    aux[PERL_MULTICONCAT_IX_PLAIN_LEN].size = utf8 ?    0 : total_len;
+    aux[PERL_MULTICONCAT_IX_PLAIN_LEN].ssize = utf8 ?    0 : total_len;
     aux[PERL_MULTICONCAT_IX_UTF8_PV].pv     = const_str;
-    aux[PERL_MULTICONCAT_IX_UTF8_LEN].size  = total_len;
+    aux[PERL_MULTICONCAT_IX_UTF8_LEN].ssize  = total_len;
 
     /* if variant > 0, calculate a variant const string and lengths where
      * the utf8 version of the string will take 'variant' more bytes than
@@ -3231,25 +3231,19 @@ S_maybe_multiconcat(pTHX_ OP *o)
         UNOP_AUX_item  *lens = aux + PERL_MULTICONCAT_IX_LENGTHS;
         UNOP_AUX_item *ulens = lens + (nargs + 1);
         char             *up = (char*)PerlMemShared_malloc(ulen);
-        UV                 n;
+        SSize_t            n;
 
         aux[PERL_MULTICONCAT_IX_UTF8_PV].pv    = up;
-        aux[PERL_MULTICONCAT_IX_UTF8_LEN].size = ulen;
+        aux[PERL_MULTICONCAT_IX_UTF8_LEN].ssize = ulen;
 
         for (n = 0; n < (nargs + 1); n++) {
-            SSize_t l, ul, i;
-            l = ul = (lens++)->size;
-            for (i = 0; i < l; i++) {
+            SSize_t i;
+            char * orig_up = up;
+            for (i = (lens++)->ssize; i > 0; i--) {
                 U8 c = *p++;
-                if (UTF8_IS_INVARIANT(c))
-                    *up++ = c;
-                else {
-                    *up++ = UTF8_EIGHT_BIT_HI(c);
-                    *up++ = UTF8_EIGHT_BIT_LO(c);
-                    ul++;
-                }
+                append_utf8_from_native_byte(c, (U8**)&up);
             }
-            (ulens++)->size = ul;
+            (ulens++)->ssize = (i < 0) ? i : up - orig_up;
         }
     }
 
@@ -4684,7 +4678,7 @@ S_move_proto_attr(pTHX_ OP **proto, OP **attrs, const GV * name,
     o = *attrs;
     if (o->op_type == OP_CONST) {
         pv = SvPV(cSVOPo_sv, pvlen);
-        if (pvlen >= 10 && memEQ(pv, "prototype(", 10)) {
+        if (memBEGINs(pv, pvlen, "prototype(")) {
             SV * const tmpsv = newSVpvn_flags(pv + 10, pvlen - 11, SvUTF8(cSVOPo_sv));
             SV ** const tmpo = cSVOPx_svp(o);
             SvREFCNT_dec(cSVOPo_sv);
@@ -4700,7 +4694,7 @@ S_move_proto_attr(pTHX_ OP **proto, OP **attrs, const GV * name,
         for (o = OpSIBLING(lasto); o; o = OpSIBLING(o)) {
             if (o->op_type == OP_CONST) {
                 pv = SvPV(cSVOPo_sv, pvlen);
-                if (pvlen >= 10 && memEQ(pv, "prototype(", 10)) {
+                if (memBEGINs(pv, pvlen, "prototype(")) {
                     SV * const tmpsv = newSVpvn_flags(pv + 10, pvlen - 11, SvUTF8(cSVOPo_sv));
                     SV ** const tmpo = cSVOPx_svp(o);
                     SvREFCNT_dec(cSVOPo_sv);
@@ -7199,9 +7193,10 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv)
 
 Constructs, checks, and returns an op of any type that involves an
 embedded C-level pointer (PV).  C<type> is the opcode.  C<flags> gives
-the eight bits of C<op_flags>.  C<pv> supplies the C-level pointer, which
-must have been allocated using C<PerlMemShared_malloc>; the memory will
-be freed when the op is destroyed.
+the eight bits of C<op_flags>.  C<pv> supplies the C-level pointer.
+Depending on the op type, the memory referenced by C<pv> may be freed
+when the op is destroyed.  If the op is of a freeing type, C<pv> must
+have been allocated using C<PerlMemShared_malloc>.
 
 =cut
 */
@@ -7605,6 +7600,33 @@ S_assignment_type(pTHX_ const OP *o)
     return ret;
 }
 
+static OP *
+S_newONCEOP(pTHX_ OP *initop, OP *padop)
+{
+    const PADOFFSET target = padop->op_targ;
+    OP *const other = newOP(OP_PADSV,
+                           padop->op_flags
+                           | ((padop->op_private & ~OPpLVAL_INTRO) << 8));
+    OP *const first = newOP(OP_NULL, 0);
+    OP *const nullop = newCONDOP(0, first, initop, other);
+    /* XXX targlex disabled for now; see ticket #124160
+       newCONDOP(0, first, S_maybe_targlex(aTHX_ initop), other);
+     */
+    OP *const condop = first->op_next;
+
+    OpTYPE_set(condop, OP_ONCE);
+    other->op_targ = target;
+    nullop->op_flags |= OPf_WANT_SCALAR;
+
+    /* Store the initializedness of state vars in a separate
+       pad entry.  */
+    condop->op_targ =
+      pad_add_name_pvn("$",1,padadd_NO_DUP_CHECK|padadd_STATE,0,0);
+    /* hijacking PADSTALE for uninitialized state variables */
+    SvPADSTALE_on(PAD_SVl(condop->op_targ));
+
+    return nullop;
+}
 
 /*
 =for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right
@@ -7649,8 +7671,9 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
     }
 
     if ((assign_type = assignment_type(left)) == ASSIGN_LIST) {
+       OP *state_var_op = NULL;
        static const char no_list_state[] = "Initialization of state variables"
-           " in list context currently forbidden";
+           " in list currently forbidden";
        OP *curop;
 
        if (left->op_type == OP_ASLICE || left->op_type == OP_HSLICE)
@@ -7664,16 +7687,29 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
 
        if (OP_TYPE_IS_OR_WAS(left, OP_LIST))
        {
-           OP* lop = ((LISTOP*)left)->op_first;
-           while (lop) {
-               if ((lop->op_type == OP_PADSV ||
-                    lop->op_type == OP_PADAV ||
-                    lop->op_type == OP_PADHV ||
-                    lop->op_type == OP_PADANY)
-                 && (lop->op_private & OPpPAD_STATE)
-                )
-                    yyerror(no_list_state);
-               lop = OpSIBLING(lop);
+           OP *lop = ((LISTOP*)left)->op_first, *vop, *eop;
+           if (!(left->op_flags & OPf_PARENS) &&
+                   lop->op_type == OP_PUSHMARK &&
+                   (vop = OpSIBLING(lop)) &&
+                   (vop->op_type == OP_PADAV || vop->op_type == OP_PADHV) &&
+                   !(vop->op_flags & OPf_PARENS) &&
+                   (vop->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)) ==
+                       (OPpLVAL_INTRO|OPpPAD_STATE) &&
+                   (eop = OpSIBLING(vop)) &&
+                   eop->op_type == OP_ENTERSUB &&
+                   !OpHAS_SIBLING(eop)) {
+               state_var_op = vop;
+           } else {
+               while (lop) {
+                   if ((lop->op_type == OP_PADSV ||
+                        lop->op_type == OP_PADAV ||
+                        lop->op_type == OP_PADHV ||
+                        lop->op_type == OP_PADANY)
+                     && (lop->op_private & OPpPAD_STATE)
+                   )
+                       yyerror(no_list_state);
+                   lop = OpSIBLING(lop);
+               }
            }
        }
        else if (  (left->op_private & OPpLVAL_INTRO)
@@ -7693,7 +7729,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                   state (%a) = ...
                   (state %a) = ...
                */
-               yyerror(no_list_state);
+                if (left->op_flags & OPf_PARENS)
+                   yyerror(no_list_state);
+               else
+                   state_var_op = left;
        }
 
         /* optimise @a = split(...) into:
@@ -7785,6 +7824,9 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                 }
             }
        }
+
+       if (state_var_op)
+           o = S_newONCEOP(aTHX_ o, state_var_op);
        return o;
     }
     if (assign_type == ASSIGN_REF)
@@ -8895,8 +8937,8 @@ S_looks_like_bool(pTHX_ const OP *o)
 =for apidoc Am|OP *|newGIVENOP|OP *cond|OP *block|PADOFFSET defsv_off
 
 Constructs, checks, and returns an op tree expressing a C<given> block.
-C<cond> supplies the expression that will be locally assigned to a lexical
-variable, and C<block> supplies the body of the C<given> construct; they
+C<cond> supplies the expression to whose value C<$_> will be locally
+aliased, and C<block> supplies the body of the C<given> construct; they
 are consumed by this function and become part of the constructed op tree.
 C<defsv_off> must be zero (it used to identity the pad slot of lexical $_).
 
@@ -8910,11 +8952,7 @@ Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off)
     PERL_UNUSED_ARG(defsv_off);
 
     assert(!defsv_off);
-    return newGIVWHENOP(
-       ref_array_or_hash(cond),
-       block,
-       OP_ENTERGIVEN, OP_LEAVEGIVEN,
-       0);
+    return newGIVWHENOP(cond, block, OP_ENTERGIVEN, OP_LEAVEGIVEN, 0);
 }
 
 /*
@@ -9201,6 +9239,8 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 
     PERL_ARGS_ASSERT_NEWMYSUB;
 
+    PL_hints |= HINT_BLOCK_SCOPE;
+
     /* Find the pad slot for storing the new sub.
        We cannot use PL_comppad, as it is the pad owned by the new sub.  We
        need to look in CvOUTSIDE and find the pad belonging to the enclos-
@@ -9576,7 +9616,7 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
           sub is stored in.  */
        const I32 flags =
           ec ? GV_NOADD_NOINIT
-             :   PL_curstash != CopSTASH(PL_curcop)
+             :   (IN_PERL_RUNTIME && PL_curstash != CopSTASH(PL_curcop))
               || memchr(name, ':', namlen) || memchr(name, '\'', namlen)
                    ? gv_fetch_flags
                    : GV_ADDMULTI | GV_NOINIT | GV_NOTQUAL;
@@ -9631,7 +9671,7 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
 
        PL_compcv = 0;
        if (name && block) {
-           const char *s = strrchr(name, ':');
+           const char *s = (char *) my_memrchr(name, ':', namlen);
            s = s ? s+1 : name;
            if (strEQ(s, "BEGIN")) {
                if (PL_in_eval & EVAL_KEEPERR)
@@ -11730,30 +11770,7 @@ Perl_ck_sassign(pTHX_ OP *o)
            )
                && (kkid->op_private & (OPpLVAL_INTRO|OPpPAD_STATE))
                    == (OPpLVAL_INTRO|OPpPAD_STATE)) {
-           const PADOFFSET target = kkid->op_targ;
-           OP *const other = newOP(OP_PADSV,
-                                   kkid->op_flags
-                                   | ((kkid->op_private & ~OPpLVAL_INTRO) << 8));
-           OP *const first = newOP(OP_NULL, 0);
-           OP *const nullop =
-               newCONDOP(0, first, o, other);
-           /* XXX targlex disabled for now; see ticket #124160
-               newCONDOP(0, first, S_maybe_targlex(aTHX_ o), other);
-            */
-           OP *const condop = first->op_next;
-
-            OpTYPE_set(condop, OP_ONCE);
-           other->op_targ = target;
-           nullop->op_flags |= OPf_WANT_SCALAR;
-
-           /* Store the initializedness of state vars in a separate
-              pad entry.  */
-           condop->op_targ =
-             pad_add_name_pvn("$",1,padadd_NO_DUP_CHECK|padadd_STATE,0,0);
-           /* hijacking PADSTALE for uninitialized state variables */
-           SvPADSTALE_on(PAD_SVl(condop->op_targ));
-
-           return nullop;
+           return S_newONCEOP(aTHX_ o, kkid);
        }
     }
     return S_maybe_targlex(aTHX_ o);
@@ -11786,7 +11803,9 @@ Perl_ck_method(pTHX_ OP *o)
     sv = kSVOP->op_sv;
 
     /* replace ' with :: */
-    while ((compatptr = strchr(SvPVX(sv), '\''))) {
+    while ((compatptr = (char *) memchr(SvPVX(sv), '\'',
+                                        SvEND(sv) - SvPVX(sv) )))
+    {
         *compatptr = ':';
         sv_insert(sv, compatptr - SvPVX_const(sv), 0, ":", 1);
     }
@@ -11807,13 +11826,13 @@ Perl_ck_method(pTHX_ OP *o)
         return newMETHOP_named(OP_METHOD_NAMED, 0, methsv);
     }
 
-    if (nsplit == 7 && memEQ(method, "SUPER::", nsplit)) { /* $proto->SUPER::method() */
+    if (memEQs(method, nsplit, "SUPER::")) { /* $proto->SUPER::method() */
         op_free(o);
         return newMETHOP_named(OP_METHOD_SUPER, 0, methsv);
     }
 
     /* $proto->MyClass::method() and $proto->MyClass::SUPER::method() */
-    if (nsplit >= 9 && strnEQ(method+nsplit-9, "::SUPER::", 9)) {
+    if (nsplit >= 9 && strBEGINs(method+nsplit-9, "::SUPER::")) {
         rclass = newSVpvn_share(method, utf8*(nsplit-9), 0);
         new_op = newMETHOP_named(OP_METHOD_REDIR_SUPER, 0, methsv);
     } else {
@@ -12162,8 +12181,6 @@ Perl_ck_sort(pTHX_ OP *o)
            SV ** const svp = hv_fetchs(hinthv, "sort", FALSE);
            if (svp) {
                const I32 sorthints = (I32)SvIV(*svp);
-               if ((sorthints & HINT_SORT_QUICKSORT) != 0)
-                   o->op_private |= OPpSORT_QSORT;
                if ((sorthints & HINT_SORT_STABLE) != 0)
                    o->op_private |= OPpSORT_STABLE;
                if ((sorthints & HINT_SORT_UNSTABLE) != 0)
@@ -12780,7 +12797,7 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
                switch (*proto++) {
                    case '[':
                        if (contextclass++ == 0) {
-                           e = strchr(proto, ']');
+                           e = (char *) memchr(proto, ']', proto_end - proto);
                            if (!e || e == proto)
                                goto oops;
                        }
@@ -13362,7 +13379,7 @@ Perl_ck_substr(pTHX_ OP *o)
        if (kid->op_type == OP_NULL)
            kid = OpSIBLING(kid);
        if (kid)
-           kid->op_flags |= OPf_MOD;
+           op_lvalue(kid, o->op_type);
 
     }
     return o;