This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use PodParser 1.18 new test.
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index eb05228..d5d5dd8 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -28,37 +28,6 @@ static double UV_MAX_cxux = ((double)UV_MAX);
 #endif
 
 /*
- * Types used in bitwise operations.
- *
- * Normally we'd just use IV and UV.  However, some hardware and
- * software combinations (e.g. Alpha and current OSF/1) don't have a
- * floating-point type to use for NV that has adequate bits to fully
- * hold an IV/UV.  (In other words, sizeof(long) == sizeof(double).)
- *
- * It just so happens that "int" is the right size almost everywhere.
- */
-typedef int IBW;
-typedef unsigned UBW;
-
-/*
- * Mask used after bitwise operations.
- *
- * There is at least one realm (Cray word machines) that doesn't
- * have an integral type (except char) small enough to be represented
- * in a double without loss; that is, it has no 32-bit type.
- */
-#if LONGSIZE > 4  && defined(_CRAY)
-#  define BW_BITS  32
-#  define BW_MASK  ((1 << BW_BITS) - 1)
-#  define BW_SIGN  (1 << (BW_BITS - 1))
-#  define BWi(i)  (((i) & BW_SIGN) ? ((i) | ~BW_MASK) : ((i) & BW_MASK))
-#  define BWu(u)  ((u) & BW_MASK)
-#else
-#  define BWi(i)  (i)
-#  define BWu(u)  (u)
-#endif
-
-/*
  * Offset for integer pack/unpack.
  *
  * On architectures where I16 and I32 aren't really 16 and 32 bits,
@@ -229,14 +198,14 @@ PP(pp_rv2gv)
     else {
        if (SvTYPE(sv) != SVt_PVGV) {
            char *sym;
-           STRLEN n_a;
+           STRLEN len;
 
            if (SvGMAGICAL(sv)) {
                mg_get(sv);
                if (SvROK(sv))
                    goto wasref;
            }
-           if (!SvOK(sv)) {
+           if (!SvOK(sv) && sv != &PL_sv_undef) {
                /* If this is a 'my' scalar and flag is set then vivify 
                 * NI-S 1999/05/07
                 */ 
@@ -267,13 +236,17 @@ PP(pp_rv2gv)
                    report_uninit();
                RETSETUNDEF;
            }
-           sym = SvPV(sv, n_a);
+           sym = SvPV(sv,len);
            if ((PL_op->op_flags & OPf_SPECIAL) &&
                !(PL_op->op_flags & OPf_MOD))
            {
                sv = (SV*)gv_fetchpv(sym, FALSE, SVt_PVGV);
-               if (!sv)
+               if (!sv
+                   && (!is_gv_magical(sym,len,0)
+                       || !(sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV))))
+               {
                    RETSETUNDEF;
+               }
            }
            else {
                if (PL_op->op_private & HINT_STRICT_REFS)
@@ -307,7 +280,7 @@ PP(pp_rv2sv)
     else {
        GV *gv = (GV*)sv;
        char *sym;
-       STRLEN n_a;
+       STRLEN len;
 
        if (SvTYPE(gv) != SVt_PVGV) {
            if (SvGMAGICAL(sv)) {
@@ -323,13 +296,17 @@ PP(pp_rv2sv)
                    report_uninit();
                RETSETUNDEF;
            }
-           sym = SvPV(sv, n_a);
+           sym = SvPV(sv, len);
            if ((PL_op->op_flags & OPf_SPECIAL) &&
                !(PL_op->op_flags & OPf_MOD))
            {
                gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PV);
-               if (!gv)
+               if (!gv
+                   && (!is_gv_magical(sym,len,0)
+                       || !(gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV))))
+               {
                    RETSETUNDEF;
+               }
            }
            else {
                if (PL_op->op_private & HINT_STRICT_REFS)
@@ -457,7 +434,7 @@ PP(pp_prototype)
                        seen_question = 1;
                        str[n++] = ';';
                    }
-                   else if (seen_question) 
+                   else if (n && str[0] == ';' && seen_question) 
                        goto set;       /* XXXX system, exec */
                    if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF 
                        && (oa & (OA_OPTIONAL - 1)) <= OA_HVREF) {
@@ -584,9 +561,13 @@ PP(pp_bless)
     else {
        SV *ssv = POPs;
        STRLEN len;
-       char *ptr = SvPV(ssv,len);
-       if (ckWARN(WARN_UNSAFE) && len == 0)
-           Perl_warner(aTHX_ WARN_UNSAFE, 
+       char *ptr;
+
+       if (ssv && !SvGMAGICAL(ssv) && !SvAMAGIC(ssv) && SvROK(ssv))
+           Perl_croak(aTHX_ "Attempt to bless into a reference");
+       ptr = SvPV(ssv,len);
+       if (ckWARN(WARN_MISC) && len == 0)
+           Perl_warner(aTHX_ WARN_MISC, 
                   "Explicit blessing to '' (assuming package main)");
        stash = gv_stashpvn(ptr, len, TRUE);
     }
@@ -622,6 +603,9 @@ PP(pp_gelem)
     case 'F':
        if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */
            tmpRef = (SV*)GvIOp(gv);
+       else
+       if (strEQ(elem, "FORMAT"))
+           tmpRef = (SV*)GvFORM(gv);
        break;
     case 'G':
        if (strEQ(elem, "GLOB"))
@@ -832,8 +816,8 @@ PP(pp_undef)
        hv_undef((HV*)sv);
        break;
     case SVt_PVCV:
-       if (ckWARN(WARN_UNSAFE) && cv_const_sv((CV*)sv))
-           Perl_warner(aTHX_ WARN_UNSAFE, "Constant subroutine %s undefined",
+       if (ckWARN(WARN_MISC) && cv_const_sv((CV*)sv))
+           Perl_warner(aTHX_ WARN_MISC, "Constant subroutine %s undefined",
                 CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv)));
        /* FALL THROUGH */
     case SVt_PVFM:
@@ -936,7 +920,7 @@ PP(pp_pow)
     djSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
     {
       dPOPTOPnnrl;
-      SETn( pow( left, right) );
+      SETn( Perl_pow( left, right) );
       RETURN;
     }
 }
@@ -992,7 +976,7 @@ PP(pp_modulo)
        NV dright;
        NV dleft;
 
-       if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+       if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
            IV i = SvIVX(POPs);
            right = (right_neg = (i < 0)) ? -i : i;
        }
@@ -1004,7 +988,7 @@ PP(pp_modulo)
                dright = -dright;
        }
 
-       if (!use_double && SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+       if (!use_double && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
            IV i = SvIVX(POPs);
            left = (left_neg = (i < 0)) ? -i : i;
        }
@@ -1041,8 +1025,8 @@ PP(pp_modulo)
 #endif
 
            /* Backward-compatibility clause: */
-           dright = floor(dright + 0.5);
-           dleft  = floor(dleft + 0.5);
+           dright = Perl_floor(dright + 0.5);
+           dleft  = Perl_floor(dleft + 0.5);
 
            if (!dright)
                DIE(aTHX_ "Illegal modulus zero");
@@ -1107,10 +1091,10 @@ PP(pp_repeat)
            SP -= items;
     }
     else {     /* Note: mark already snarfed by pp_list */
-       SV *tmpstr;
+       SV *tmpstr = POPs;
        STRLEN len;
+       bool isutf = DO_UTF8(tmpstr);
 
-       tmpstr = POPs;
        SvSetSV(TARG, tmpstr);
        SvPV_force(TARG, len);
        if (count != 1) {
@@ -1123,7 +1107,10 @@ PP(pp_repeat)
            }
            *SvEND(TARG) = '\0';
        }
-       (void)SvPOK_only(TARG);
+       if (isutf)
+           (void)SvPOK_only_UTF8(TARG);
+       else
+           (void)SvPOK_only(TARG);
        PUSHTARG;
     }
     RETURN;
@@ -1144,16 +1131,14 @@ PP(pp_left_shift)
 {
     djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
     {
-      IBW shift = POPi;
+      IV shift = POPi;
       if (PL_op->op_private & HINT_INTEGER) {
-       IBW i = TOPi;
-       i = BWi(i) << shift;
-       SETi(BWi(i));
+       IV i = TOPi;
+       SETi(i << shift);
       }
       else {
-       UBW u = TOPu;
-       u <<= shift;
-       SETu(BWu(u));
+       UV u = TOPu;
+       SETu(u << shift);
       }
       RETURN;
     }
@@ -1163,16 +1148,14 @@ PP(pp_right_shift)
 {
     djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
     {
-      IBW shift = POPi;
+      IV shift = POPi;
       if (PL_op->op_private & HINT_INTEGER) {
-       IBW i = TOPi;
-       i = BWi(i) >> shift;
-       SETi(BWi(i));
+       IV i = TOPi;
+       SETi(i >> shift);
       }
       else {
-       UBW u = TOPu;
-       u >>= shift;
-       SETu(BWu(u));
+       UV u = TOPu;
+       SETu(u >> shift);
       }
       RETURN;
     }
@@ -1235,6 +1218,13 @@ PP(pp_ncmp)
       dPOPTOPnnrl;
       I32 value;
 
+#ifdef Perl_isnan
+      if (Perl_isnan(left) || Perl_isnan(right)) {
+         SETs(&PL_sv_undef);
+         RETURN;
+       }
+      value = (left > right) - (left < right);
+#else
       if (left == right)
        value = 0;
       else if (left < right)
@@ -1245,6 +1235,7 @@ PP(pp_ncmp)
        SETs(&PL_sv_undef);
        RETURN;
       }
+#endif
       SETi(value);
       RETURN;
     }
@@ -1342,12 +1333,12 @@ PP(pp_bit_and)
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
        if (PL_op->op_private & HINT_INTEGER) {
-         IBW value = SvIV(left) & SvIV(right);
-         SETi(BWi(value));
+         IV i = SvIV(left) & SvIV(right);
+         SETi(i);
        }
        else {
-         UBW value = SvUV(left) & SvUV(right);
-         SETu(BWu(value));
+         UV u = SvUV(left) & SvUV(right);
+         SETu(u);
        }
       }
       else {
@@ -1365,12 +1356,12 @@ PP(pp_bit_xor)
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
        if (PL_op->op_private & HINT_INTEGER) {
-         IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
-         SETi(BWi(value));
+         IV i = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
+         SETi(i);
        }
        else {
-         UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
-         SETu(BWu(value));
+         UV u = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
+         SETu(u);
        }
       }
       else {
@@ -1388,12 +1379,12 @@ PP(pp_bit_or)
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
        if (PL_op->op_private & HINT_INTEGER) {
-         IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
-         SETi(BWi(value));
+         IV i = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
+         SETi(i);
        }
        else {
-         UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
-         SETu(BWu(value));
+         UV u = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
+         SETu(u);
        }
       }
       else {
@@ -1411,9 +1402,23 @@ PP(pp_negate)
        dTOPss;
        if (SvGMAGICAL(sv))
            mg_get(sv);
-       if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv) && SvIVX(sv) != IV_MIN)
-           SETi(-SvIVX(sv));
-       else if (SvNIOKp(sv))
+       if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv)) {
+           if (SvIsUV(sv)) {
+               if (SvIVX(sv) == IV_MIN) {
+                   SETi(SvIVX(sv));    /* special case: -((UV)IV_MAX+1) == IV_MIN */
+                   RETURN;
+               }
+               else if (SvUVX(sv) <= IV_MAX) {
+                   SETi(-SvIVX(sv));
+                   RETURN;
+               }
+           }
+           else if (SvIVX(sv) != IV_MIN) {
+               SETi(-SvIVX(sv));
+               RETURN;
+           }
+       }
+       if (SvNIOKp(sv))
            SETn(-SvNV(sv));
        else if (SvPOKp(sv)) {
            STRLEN len;
@@ -1454,12 +1459,12 @@ PP(pp_complement)
       dTOPss;
       if (SvNIOKp(sv)) {
        if (PL_op->op_private & HINT_INTEGER) {
-         IBW value = ~SvIV(sv);
-         SETi(BWi(value));
+         IV i = ~SvIV(sv);
+         SETi(i);
        }
        else {
-         UBW value = ~SvUV(sv);
-         SETu(BWu(value));
+         UV u = ~SvUV(sv);
+         SETu(u);
        }
       }
       else {
@@ -1815,7 +1820,7 @@ PP(pp_log)
       NV value;
       value = POPn;
       if (value <= 0.0) {
-       RESTORE_NUMERIC_STANDARD();
+       SET_NUMERIC_STANDARD();
        DIE(aTHX_ "Can't take log of %g", value);
       }
       value = Perl_log(value);
@@ -1831,7 +1836,7 @@ PP(pp_sqrt)
       NV value;
       value = POPn;
       if (value < 0.0) {
-       RESTORE_NUMERIC_STANDARD();
+       SET_NUMERIC_STANDARD();
        DIE(aTHX_ "Can't take sqrt of %g", value);
       }
       value = Perl_sqrt(value);
@@ -1898,6 +1903,7 @@ PP(pp_hex)
     STRLEN n_a;
 
     tmps = POPpx;
+    argtype = 1;               /* allow underscores */
     XPUSHn(scan_hex(tmps, 99, &argtype));
     RETURN;
 }
@@ -1915,6 +1921,7 @@ PP(pp_oct)
        tmps++;
     if (*tmps == '0')
        tmps++;
+    argtype = 1;               /* allow underscores */
     if (*tmps == 'x')
        value = scan_hex(++tmps, 99, &argtype);
     else if (*tmps == 'b')
@@ -2012,17 +2019,19 @@ PP(pp_substr)
        rem -= pos;
     }
     if (fail < 0) {
-       if (ckWARN(WARN_SUBSTR) || lvalue || repl)
+       if (lvalue || repl)
+           Perl_croak(aTHX_ "substr outside of string");
+       if (ckWARN(WARN_SUBSTR))
            Perl_warner(aTHX_ WARN_SUBSTR, "substr outside of string");
        RETPUSHUNDEF;
     }
     else {
-        if (utfcurlen) {
+       if (utfcurlen)
            sv_pos_u2b(sv, &pos, &rem);
-           SvUTF8_on(TARG);
-       }
        tmps += pos;
        sv_setpvn(TARG, tmps, rem);
+       if (utfcurlen)
+           SvUTF8_on(TARG);
        if (repl)
            sv_insert(sv, pos, rem, repl, repl_len);
        else if (lvalue) {              /* it's an lvalue! */
@@ -2035,7 +2044,7 @@ PP(pp_substr)
                                "Attempt to use reference as lvalue in substr");
                }
                if (SvOK(sv))           /* is it defined ? */
-                   (void)SvPOK_only(sv);
+                   (void)SvPOK_only_UTF8(sv);
                else
                    sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
            }
@@ -2201,14 +2210,14 @@ PP(pp_chr)
 
     (void)SvUPGRADE(TARG,SVt_PV);
 
-    if (value > 255 && !IN_BYTE) {
-       SvGROW(TARG,8);
+    if ((value > 255 && !IN_BYTE) || (value & 0x80 && PL_hints & HINT_UTF8) ) {
+       SvGROW(TARG, UTF8_MAXLEN+1);
        tmps = SvPVX(TARG);
        tmps = (char*)uv_to_utf8((U8*)tmps, (UV)value);
        SvCUR_set(TARG, tmps - SvPVX(TARG));
        *tmps = '\0';
-       SvUTF8_on(TARG);
        (void)SvPOK_only(TARG);
+       SvUTF8_on(TARG);
        XPUSHs(TARG);
        RETURN;
     }
@@ -2218,7 +2227,6 @@ PP(pp_chr)
     tmps = SvPVX(TARG);
     *tmps++ = value;
     *tmps = '\0';
-    SvUTF8_off(TARG);                          /* decontaminate */
     (void)SvPOK_only(TARG);
     XPUSHs(TARG);
     RETURN;
@@ -2252,7 +2260,7 @@ PP(pp_ucfirst)
 
     if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
        I32 ulen;
-       U8 tmpbuf[10];
+       U8 tmpbuf[UTF8_MAXLEN];
        U8 *tend;
        UV uv = utf8_to_uv(s, &ulen);
 
@@ -2311,7 +2319,7 @@ PP(pp_lcfirst)
 
     if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
        I32 ulen;
-       U8 tmpbuf[10];
+       U8 tmpbuf[UTF8_MAXLEN];
        U8 *tend;
        UV uv = utf8_to_uv(s, &ulen);
 
@@ -2551,7 +2559,7 @@ PP(pp_quotemeta)
        }
        *d = '\0';
        SvCUR_set(TARG, d - SvPVX(TARG));
-       (void)SvPOK_only(TARG);
+       (void)SvPOK_only_UTF8(TARG);
     }
     else
        sv_setpvn(TARG, s, len);
@@ -2881,8 +2889,8 @@ PP(pp_anonhash)
        SV *val = NEWSV(46, 0);
        if (MARK < SP)
            sv_setsv(val, *++MARK);
-       else if (ckWARN(WARN_UNSAFE))
-           Perl_warner(aTHX_ WARN_UNSAFE, "Odd number of elements in hash assignment");
+       else if (ckWARN(WARN_MISC))
+           Perl_warner(aTHX_ WARN_MISC, "Odd number of elements in hash assignment");
        (void)hv_store_ent(hv,key,val,0);
     }
     SP = ORIGMARK;
@@ -2905,7 +2913,7 @@ PP(pp_splice)
     SV **tmparyval = 0;
     MAGIC *mg;
 
-    if (mg = SvTIED_mg((SV*)ary, 'P')) {
+    if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
        *MARK-- = SvTIED_obj((SV*)ary, mg);
        PUSHMARK(MARK);
        PUTBACK;
@@ -3099,7 +3107,7 @@ PP(pp_push)
     register SV *sv = &PL_sv_undef;
     MAGIC *mg;
 
-    if (mg = SvTIED_mg((SV*)ary, 'P')) {
+    if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
        *MARK-- = SvTIED_obj((SV*)ary, mg);
        PUSHMARK(MARK);
        PUTBACK;
@@ -3155,7 +3163,7 @@ PP(pp_unshift)
     register I32 i = 0;
     MAGIC *mg;
 
-    if (mg = SvTIED_mg((SV*)ary, 'P')) {
+    if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
        *MARK-- = SvTIED_obj((SV*)ary, mg);
        PUSHMARK(MARK);
        PUTBACK;
@@ -3240,7 +3248,7 @@ PP(pp_reverse)
                *up++ = *down;
                *down-- = tmp;
            }
-           (void)SvPOK_only(TARG);
+           (void)SvPOK_only_UTF8(TARG);
        }
        SP = MARK + 1;
        SETTARG;
@@ -3392,8 +3400,8 @@ PP(pp_unpack)
        default:
            DIE(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
-           if (commas++ == 0 && ckWARN(WARN_UNSAFE))
-               Perl_warner(aTHX_ WARN_UNSAFE,
+           if (commas++ == 0 && ckWARN(WARN_UNPACK))
+               Perl_warner(aTHX_ WARN_UNPACK,
                            "Invalid type in unpack: '%c'", (int)datumtype);
            break;
        case '%':
@@ -4174,7 +4182,7 @@ PP(pp_unpack)
                 int i;
  
                 for (i = 0; i < sizeof(PL_uuemap); i += 1)
-                    PL_uudmap[PL_uuemap[i]] = i;
+                    PL_uudmap[(U8)PL_uuemap[i]] = i;
                 /*
                  * Because ' ' and '`' map to the same value,
                  * we need to decode them both the same.
@@ -4191,22 +4199,22 @@ PP(pp_unpack)
                char hunk[4];
 
                hunk[3] = '\0';
-               len = PL_uudmap[*s++] & 077;
+               len = PL_uudmap[*(U8*)s++] & 077;
                while (len > 0) {
                    if (s < strend && ISUUCHAR(*s))
-                       a = PL_uudmap[*s++] & 077;
+                       a = PL_uudmap[*(U8*)s++] & 077;
                    else
                        a = 0;
                    if (s < strend && ISUUCHAR(*s))
-                       b = PL_uudmap[*s++] & 077;
+                       b = PL_uudmap[*(U8*)s++] & 077;
                    else
                        b = 0;
                    if (s < strend && ISUUCHAR(*s))
-                       c = PL_uudmap[*s++] & 077;
+                       c = PL_uudmap[*(U8*)s++] & 077;
                    else
                        c = 0;
                    if (s < strend && ISUUCHAR(*s))
-                       d = PL_uudmap[*s++] & 077;
+                       d = PL_uudmap[*(U8*)s++] & 077;
                    else
                        d = 0;
                    hunk[0] = (a << 2) | (b >> 4);
@@ -4374,6 +4382,7 @@ PP(pp_pack)
     register I32 items;
     STRLEN fromlen;
     register char *pat = SvPVx(*++MARK, fromlen);
+    char *patcopy;
     register char *patend = pat + fromlen;
     register I32 len;
     I32 datumtype;
@@ -4404,6 +4413,7 @@ PP(pp_pack)
     items = SP - MARK;
     MARK++;
     sv_setpvn(cat, "", 0);
+    patcopy = pat;
     while (pat < patend) {
        SV *lengthcode = Nullsv;
 #define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *MARK++ : &PL_sv_no)
@@ -4411,8 +4421,12 @@ PP(pp_pack)
 #ifdef PERL_NATINT_PACK
        natint = 0;
 #endif
-       if (isSPACE(datumtype))
+       if (isSPACE(datumtype)) {
+           patcopy++;
            continue;
+        }
+       if (datumtype == 'U' && pat == patcopy+1) 
+           SvUTF8_on(cat);
        if (datumtype == '#') {
            while (pat < patend && *pat != '\n')
                pat++;
@@ -4446,17 +4460,18 @@ PP(pp_pack)
            len = 1;
        if (*pat == '/') {
            ++pat;
-           if (*pat != 'a' && *pat != 'A' && *pat != 'Z' || pat[1] != '*')
+           if ((*pat != 'a' && *pat != 'A' && *pat != 'Z') || pat[1] != '*')
                DIE(aTHX_ "/ must be followed by a*, A* or Z*");
            lengthcode = sv_2mortal(newSViv(sv_len(items > 0
-                                                  ? *MARK : &PL_sv_no)));
+                                                  ? *MARK : &PL_sv_no)
+                                            + (*pat == 'Z' ? 1 : 0)));
        }
        switch(datumtype) {
        default:
            DIE(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
-           if (commas++ == 0 && ckWARN(WARN_UNSAFE))
-               Perl_warner(aTHX_ WARN_UNSAFE,
+           if (commas++ == 0 && ckWARN(WARN_PACK))
+               Perl_warner(aTHX_ WARN_PACK,
                            "Invalid type in pack: '%c'", (int)datumtype);
            break;
        case '%':
@@ -4643,7 +4658,7 @@ PP(pp_pack)
            while (len-- > 0) {
                fromstr = NEXTFROM;
                auint = SvUV(fromstr);
-               SvGROW(cat, SvCUR(cat) + 10);
+               SvGROW(cat, SvCUR(cat) + UTF8_MAXLEN);
                SvCUR_set(cat, (char*)uv_to_utf8((U8*)SvEND(cat),auint)
                               - SvPVX(cat));
            }
@@ -4747,14 +4762,14 @@ PP(pp_pack)
                    DIE(aTHX_ "Cannot compress negative numbers");
 
                if (
-#ifdef BW_BITS
-                   adouble <= BW_MASK
+#if UVSIZE > 4 && UVSIZE >= NVSIZE
+                   adouble <= 0xffffffff
 #else
-#ifdef CXUX_BROKEN_CONSTANT_CONVERT
+#   ifdef CXUX_BROKEN_CONSTANT_CONVERT
                    adouble <= UV_MAX_cxux
-#else
+#   else
                    adouble <= UV_MAX
-#endif
+#   endif
 #endif
                    )
                {
@@ -4908,11 +4923,11 @@ PP(pp_pack)
                     * of pack() (and all copies of the result) are
                     * gone.
                     */
-                   if (ckWARN(WARN_UNSAFE) && (SvTEMP(fromstr)
+                   if (ckWARN(WARN_PACK) && (SvTEMP(fromstr)
                                                || (SvPADTMP(fromstr)
                                                    && !SvREADONLY(fromstr))))
                    {
-                       Perl_warner(aTHX_ WARN_UNSAFE,
+                       Perl_warner(aTHX_ WARN_PACK,
                                "Attempt to pack pointer to temporary value");
                    }
                    if (SvPOK(fromstr) || SvNIOK(fromstr))
@@ -5012,7 +5027,7 @@ PP(pp_split)
        av_extend(ary,0);
        av_clear(ary);
        SPAGAIN;
-       if (mg = SvTIED_mg((SV*)ary, 'P')) {
+       if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
            PUSHMARK(SP);
            XPUSHs(SvTIED_obj((SV*)ary, mg));
        }
@@ -5255,24 +5270,7 @@ PP(pp_lock)
     dTOPss;
     SV *retsv = sv;
 #ifdef USE_THREADS
-    MAGIC *mg;
-
-    if (SvROK(sv))
-       sv = SvRV(sv);
-
-    mg = condpair_magic(sv);
-    MUTEX_LOCK(MgMUTEXP(mg));
-    if (MgOWNER(mg) == thr)
-       MUTEX_UNLOCK(MgMUTEXP(mg));
-    else {
-       while (MgOWNER(mg))
-           COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg));
-       MgOWNER(mg) = thr;
-       DEBUG_S(PerlIO_printf(Perl_debug_log, "0x%"UVxf": pp_lock lock 0x%"UVxf"\n",
-                             PTR2UV(thr), PTR2UV(sv));)
-       MUTEX_UNLOCK(MgMUTEXP(mg));
-       SAVEDESTRUCTOR_X(Perl_unlock_condpair, sv);
-    }
+    sv_lock(sv);
 #endif /* USE_THREADS */
     if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV
        || SvTYPE(retsv) == SVt_PVCV) {
@@ -5284,8 +5282,8 @@ PP(pp_lock)
 
 PP(pp_threadsv)
 {
-    djSP;
 #ifdef USE_THREADS
+    djSP;
     EXTEND(SP, 1);
     if (PL_op->op_private & OPpLVAL_INTRO)
        PUSHs(*save_threadsv(PL_op->op_targ));