This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regexec.c: Convert two !=0's to cBOOL
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index aa6b790..def677b 100644 (file)
--- a/sv.c
+++ b/sv.c
 #include "perl.h"
 #include "regcomp.h"
 
+#ifndef HAS_C99
+# if __STDC_VERSION__ >= 199901L && !defined(VMS)
+#  define HAS_C99 1
+# endif
+#endif
+#if HAS_C99
+# include <stdint.h>
+#endif
+
 #define FCALL *f
 
 #ifdef __Lynx__
@@ -71,7 +80,7 @@ many types, a pointer to the body (struct xrv, xpv, xpviv...), which
 contains fields specific to each type.  Some types store all they need
 in the head, so don't have a body.
 
-In all but the most memory-paranoid configuations (ex: PURIFY), heads
+In all but the most memory-paranoid configurations (ex: PURIFY), heads
 and bodies are allocated out of arenas, which by default are
 approximately 4K chunks of memory parcelled up into N heads or bodies.
 Sv-bodies are allocated by their sv-type, guaranteeing size
@@ -542,6 +551,15 @@ do_clean_named_io_objs(pTHX_ SV *const sv)
     SvREFCNT_dec(sv); /* undo the inc above */
 }
 
+/* Void wrapper to pass to visit() */
+static void
+do_curse(pTHX_ SV * const sv) {
+    if ((PL_stderrgv && GvGP(PL_stderrgv) && (SV*)GvIO(PL_stderrgv) == sv)
+     || (PL_defoutgv && GvGP(PL_defoutgv) && (SV*)GvIO(PL_defoutgv) == sv))
+       return;
+    (void)curse(sv, 0);
+}
+
 /*
 =for apidoc sv_clean_objs
 
@@ -562,6 +580,9 @@ Perl_sv_clean_objs(pTHX)
      * error messages, close files etc */
     visit(do_clean_named_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP);
     visit(do_clean_named_io_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP);
+    /* And if there are some very tenacious barnacles clinging to arrays,
+       closures, or what have you.... */
+    visit(do_curse, SVs_OBJECT, SVs_OBJECT);
     olddef = PL_defoutgv;
     PL_defoutgv = NULL; /* disable skip of PL_defoutgv */
     if (olddef && isGV_with_GP(olddef))
@@ -1047,7 +1068,7 @@ Perl_more_bodies (pTHX_ const svtype sv_type, const size_t body_size,
        Remember, this is integer division:  */
     end = start + good_arena_size / body_size * body_size;
 
-    /* computed count doesnt reflect the 1st slot reservation */
+    /* computed count doesn't reflect the 1st slot reservation */
 #if defined(MYMALLOC) || defined(HAS_MALLOC_GOOD_SIZE)
     DEBUG_m(PerlIO_printf(Perl_debug_log,
                          "arena %p end %p arena-size %d (from %d) type %d "
@@ -2290,7 +2311,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags)
                SV * tmpstr;
                if (flags & SV_SKIP_OVERLOAD)
                    return 0;
-               tmpstr=AMG_CALLun(sv,numer);
+               tmpstr = AMG_CALLunary(sv, numer_amg);
                if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
                    return SvIV(tmpstr);
                }
@@ -2369,7 +2390,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags)
                SV *tmpstr;
                if (flags & SV_SKIP_OVERLOAD)
                    return 0;
-               tmpstr = AMG_CALLun(sv,numer);
+               tmpstr = AMG_CALLunary(sv, numer_amg);
                if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
                    return SvUV(tmpstr);
                }
@@ -2443,7 +2464,7 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
                SV *tmpstr;
                if (flags & SV_SKIP_OVERLOAD)
                    return 0;
-               tmpstr = AMG_CALLun(sv,numer);
+               tmpstr = AMG_CALLunary(sv, numer_amg);
                 if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
                    return SvNV(tmpstr);
                }
@@ -2642,7 +2663,7 @@ Perl_sv_2num(pTHX_ register SV *const sv)
     if (!SvROK(sv))
        return sv;
     if (SvAMAGIC(sv)) {
-       SV * const tmpsv = AMG_CALLun(sv,numer);
+       SV * const tmpsv = AMG_CALLunary(sv, numer_amg);
        TAINT_IF(tmpsv && SvTAINTED(tmpsv));
        if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
            return sv_2num(tmpsv);
@@ -2761,7 +2782,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
                SV *tmpstr;
                if (flags & SV_SKIP_OVERLOAD)
                    return NULL;
-               tmpstr = AMG_CALLun(sv,string);
+               tmpstr = AMG_CALLunary(sv, string_amg);
                TAINT_IF(tmpstr && SvTAINTED(tmpstr));
                if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
                    /* Unwrap this:  */
@@ -2869,7 +2890,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
                        retval -= stashnamelen;
                        memcpy(retval, stashname, stashnamelen);
                    }
-                   /* retval may not neccesarily have reached the start of the
+                   /* retval may not necessarily have reached the start of the
                       buffer here.  */
                    assert (retval >= buffer);
 
@@ -3084,7 +3105,7 @@ Perl_sv_2bool_flags(pTHX_ register SV *const sv, const I32 flags)
        return 0;
     if (SvROK(sv)) {
        if (SvAMAGIC(sv)) {
-           SV * const tmpsv = AMG_CALLun(sv,bool_);
+           SV * const tmpsv = AMG_CALLunary(sv, bool__amg);
            if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
                return cBOOL(SvTRUE(tmpsv));
        }
@@ -4557,7 +4578,7 @@ Perl_sv_usepvn_flags(pTHX_ SV *const sv, char *ptr, const STRLEN len, const U32
 #endif
     if (flags & SV_HAS_TRAILING_NUL) {
        /* It's long enough - do nothing.
-          Specfically Perl_newCONSTSUB is relying on this.  */
+          Specifically Perl_newCONSTSUB is relying on this.  */
     } else {
 #ifdef DEBUGGING
        /* Force a move to shake out bugs in callers.  */
@@ -4713,7 +4734,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags)
     else if (SvFAKE(sv) && isGV_with_GP(sv))
        sv_unglob(sv);
     else if (SvFAKE(sv) && SvTYPE(sv) == SVt_REGEXP) {
-       /* Need to downgrade the REGEXP to a simple(r) scalar. This is analagous
+       /* Need to downgrade the REGEXP to a simple(r) scalar. This is analogous
           to sv_unglob. We only need it here, so inline it.  */
        const svtype new_type = SvMAGIC(sv) || SvSTASH(sv) ? SVt_PVMG : SVt_PV;
        SV *const temp = newSV_type(new_type);
@@ -5118,7 +5139,7 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how,
            mg->mg_ptr = savepvn(name, namlen);
        else if (namlen == HEf_SVKEY) {
            /* Yes, this is casting away const. This is only for the case of
-              HEf_SVKEY. I think we need to document this abberation of the
+              HEf_SVKEY. I think we need to document this aberation of the
               constness of the API, rather than making name non-const, as
               that change propagating outwards a long way.  */
            mg->mg_ptr = (char*)SvREFCNT_inc_simple_NN((SV *)name);
@@ -5330,31 +5351,23 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how,
     }
 }
 
-/*
-=for apidoc sv_unmagic
-
-Removes all magic of type C<type> from an SV.
-
-=cut
-*/
-
 int
-Perl_sv_unmagic(pTHX_ SV *const sv, const int type)
+S_sv_unmagicext_flags(pTHX_ SV *const sv, const int type, MGVTBL *vtbl, const U32 flags)
 {
     MAGIC* mg;
     MAGIC** mgp;
 
-    PERL_ARGS_ASSERT_SV_UNMAGIC;
+    assert(flags <= 1);
 
     if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv))
        return 0;
     mgp = &(((XPVMG*) SvANY(sv))->xmg_u.xmg_magic);
     for (mg = *mgp; mg; mg = *mgp) {
-       if (mg->mg_type == type) {
-            const MGVTBL* const vtbl = mg->mg_virtual;
+       const MGVTBL* const virt = mg->mg_virtual;
+       if (mg->mg_type == type && (!flags || virt == vtbl)) {
            *mgp = mg->mg_moremagic;
-           if (vtbl && vtbl->svt_free)
-               vtbl->svt_free(aTHX_ sv, mg);
+           if (virt && virt->svt_free)
+               virt->svt_free(aTHX_ sv, mg);
            if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
                if (mg->mg_len > 0)
                    Safefree(mg->mg_ptr);
@@ -5382,6 +5395,36 @@ Perl_sv_unmagic(pTHX_ SV *const sv, const int type)
 }
 
 /*
+=for apidoc sv_unmagic
+
+Removes all magic of type C<type> from an SV.
+
+=cut
+*/
+
+int
+Perl_sv_unmagic(pTHX_ SV *const sv, const int type)
+{
+    PERL_ARGS_ASSERT_SV_UNMAGIC;
+    return S_sv_unmagicext_flags(aTHX_ sv, type, NULL, 0);
+}
+
+/*
+=for apidoc sv_unmagicext
+
+Removes all magic of type C<type> with the specified C<vtbl> from an SV.
+
+=cut
+*/
+
+int
+Perl_sv_unmagicext(pTHX_ SV *const sv, const int type, MGVTBL *vtbl)
+{
+    PERL_ARGS_ASSERT_SV_UNMAGICEXT;
+    return S_sv_unmagicext_flags(aTHX_ sv, type, vtbl, 1);
+}
+
+/*
 =for apidoc sv_rvweaken
 
 Weaken a reference: set the C<SvWEAKREF> flag on this RV; give the
@@ -5948,65 +5991,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
        }
 
        if (SvOBJECT(sv)) {
-           if (PL_defstash &&  /* Still have a symbol table? */
-               SvDESTROYABLE(sv))
-           {
-               dSP;
-               HV* stash;
-               do {
-                   CV* destructor;
-                   stash = SvSTASH(sv);
-                   destructor = StashHANDLER(stash,DESTROY);
-                   if (destructor
-                       /* A constant subroutine can have no side effects, so
-                          don't bother calling it.  */
-                       && !CvCONST(destructor)
-                       /* Don't bother calling an empty destructor */
-                       && (CvISXSUB(destructor)
-                       || (CvSTART(destructor)
-                           && (CvSTART(destructor)->op_next->op_type
-                                               != OP_LEAVESUB))))
-                   {
-                       SV* const tmpref = newRV(sv);
-                       SvREADONLY_on(tmpref); /* DESTROY() could be naughty */
-                       ENTER;
-                       PUSHSTACKi(PERLSI_DESTROY);
-                       EXTEND(SP, 2);
-                       PUSHMARK(SP);
-                       PUSHs(tmpref);
-                       PUTBACK;
-                       call_sv(MUTABLE_SV(destructor),
-                                   G_DISCARD|G_EVAL|G_KEEPERR|G_VOID);
-                       POPSTACK;
-                       SPAGAIN;
-                       LEAVE;
-                       if(SvREFCNT(tmpref) < 2) {
-                           /* tmpref is not kept alive! */
-                           SvREFCNT(sv)--;
-                           SvRV_set(tmpref, NULL);
-                           SvROK_off(tmpref);
-                       }
-                       SvREFCNT_dec(tmpref);
-                   }
-               } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
-
-
-               if (SvREFCNT(sv)) {
-                   if (PL_in_clean_objs)
-                       Perl_croak(aTHX_
-                           "DESTROY created new reference to dead object '%s'",
-                           HvNAME_get(stash));
-                   /* DESTROY gave object new lease on life */
-                   goto get_next_sv;
-               }
-           }
-
-           if (SvOBJECT(sv)) {
-               SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */
-               SvOBJECT_off(sv);       /* Curse the object. */
-               if (type != SVt_PVIO)
-                   --PL_sv_objcount;/* XXX Might want something more general */
-           }
+           if (!curse(sv, 1)) goto get_next_sv;
        }
        if (type >= SVt_PVMG) {
            if (type == SVt_PVMG && SvPAD_OUR(sv)) {
@@ -6232,6 +6217,78 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
     } /* while sv */
 }
 
+/* This routine curses the sv itself, not the object referenced by sv. So
+   sv does not have to be ROK. */
+
+static bool
+S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
+    dVAR;
+
+    PERL_ARGS_ASSERT_CURSE;
+    assert(SvOBJECT(sv));
+
+    if (PL_defstash && /* Still have a symbol table? */
+       SvDESTROYABLE(sv))
+    {
+       dSP;
+       HV* stash;
+       do {
+           CV* destructor;
+           stash = SvSTASH(sv);
+           destructor = StashHANDLER(stash,DESTROY);
+           if (destructor
+               /* A constant subroutine can have no side effects, so
+                  don't bother calling it.  */
+               && !CvCONST(destructor)
+               /* Don't bother calling an empty destructor */
+               && (CvISXSUB(destructor)
+               || (CvSTART(destructor)
+                   && (CvSTART(destructor)->op_next->op_type
+                                       != OP_LEAVESUB))))
+           {
+               SV* const tmpref = newRV(sv);
+               SvREADONLY_on(tmpref); /* DESTROY() could be naughty */
+               ENTER;
+               PUSHSTACKi(PERLSI_DESTROY);
+               EXTEND(SP, 2);
+               PUSHMARK(SP);
+               PUSHs(tmpref);
+               PUTBACK;
+               call_sv(MUTABLE_SV(destructor),
+                           G_DISCARD|G_EVAL|G_KEEPERR|G_VOID);
+               POPSTACK;
+               SPAGAIN;
+               LEAVE;
+               if(SvREFCNT(tmpref) < 2) {
+                   /* tmpref is not kept alive! */
+                   SvREFCNT(sv)--;
+                   SvRV_set(tmpref, NULL);
+                   SvROK_off(tmpref);
+               }
+               SvREFCNT_dec(tmpref);
+           }
+       } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
+
+
+       if (check_refcnt && SvREFCNT(sv)) {
+           if (PL_in_clean_objs)
+               Perl_croak(aTHX_
+                   "DESTROY created new reference to dead object '%s'",
+                   HvNAME_get(stash));
+           /* DESTROY gave object new lease on life */
+           return FALSE;
+       }
+    }
+
+    if (SvOBJECT(sv)) {
+       SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */
+       SvOBJECT_off(sv);       /* Curse the object. */
+       if (SvTYPE(sv) != SVt_PVIO)
+           --PL_sv_objcount;/* XXX Might want something more general */
+    }
+    return TRUE;
+}
+
 /*
 =for apidoc sv_newref
 
@@ -6803,7 +6860,7 @@ S_utf8_mg_pos_cache_update(pTHX_ SV *const sv, MAGIC **const mgp, const STRLEN b
 
        /* Cache has 2 slots in use, and we know three potential pairs.
           Keep the two that give the lowest RMS distance. Do the
-          calcualation in bytes simply because we always know the byte
+          calculation in bytes simply because we always know the byte
           length.  squareroot has the same ordering as the positive value,
           so don't bother with the actual square root.  */
        const float existing = THREEWAY_SQUARE(0, cache[3], cache[1], blen);
@@ -7696,7 +7753,7 @@ screamer2:
        }
        else {
            cnt = PerlIO_read(fp,(char*)buf, sizeof(buf));
-           /* Accomodate broken VAXC compiler, which applies U8 cast to
+           /* Accommodate broken VAXC compiler, which applies U8 cast to
             * both args of ?: operator, causing EOF to change into 255
             */
            if (cnt > 0)
@@ -7796,7 +7853,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv)
        }
        if (SvROK(sv)) {
            IV i;
-           if (SvAMAGIC(sv) && AMG_CALLun(sv,inc))
+           if (SvAMAGIC(sv) && AMG_CALLunary(sv, inc_amg))
                return;
            i = PTR2IV(SvRV(sv));
            sv_unref(sv);
@@ -7977,7 +8034,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv)
        }
        if (SvROK(sv)) {
            IV i;
-           if (SvAMAGIC(sv) && AMG_CALLun(sv,dec))
+           if (SvAMAGIC(sv) && AMG_CALLunary(sv, dec_amg))
                return;
            i = PTR2IV(SvRV(sv));
            sv_unref(sv);
@@ -8167,11 +8224,11 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags
     sv_setpvn(sv,s,len);
 
     /* This code used to a sv_2mortal(), however we now unroll the call to sv_2mortal()
-     * and do what it does outselves here.
+     * and do what it does ourselves here.
      * Since we have asserted that flags can only have the SVf_UTF8 and/or SVs_TEMP flags
      * set above we can use it to enable the sv flags directly (bypassing SvTEMP_on), which
      * in turn means we dont need to mask out the SVf_UTF8 flag below, which means that we
-     * eleminate quite a few steps than it looks - Yves (explaining patch by gfx)
+     * eliminate quite a few steps than it looks - Yves (explaining patch by gfx)
      */
 
     SvFLAGS(sv) |= flags;
@@ -8790,7 +8847,8 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref)
     default:
        if (SvROK(sv)) {
            SvGETMAGIC(sv);
-           sv = amagic_deref_call(sv, to_cv_amg);
+           if (SvAMAGIC(sv))
+               sv = amagic_deref_call(sv, to_cv_amg);
            /* At this point I'd like to do SPAGAIN, but really I need to
               force it upon my callers. Hmmm. This is a mess... */
 
@@ -9027,7 +9085,7 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 
        case SVt_PVLV:          return (char *)  (SvROK(sv) ? "REF"
                                /* tied lvalues should appear to be
-                                * scalars for backwards compatitbility */
+                                * scalars for backwards compatibility */
                                : (LvTYPE(sv) == 't' || LvTYPE(sv) == 'T')
                                    ? "SCALAR" : "LVALUE");
        case SVt_PVAV:          return "ARRAY";
@@ -10247,16 +10305,28 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
 #endif
        case 'l':
 #if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
-           if (*(q + 1) == 'l') {      /* lld, llf */
+           if (*++q == 'l') {  /* lld, llf */
                intsize = 'q';
-               q += 2;
-               break;
-            }
+               ++q;
+           }
+           else
 #endif
-           /*FALLTHROUGH*/
+               intsize = 'l';
+           break;
        case 'h':
-           /*FALLTHROUGH*/
+           if (*++q == 'h') {  /* hhd, hhu */
+               intsize = 'c';
+               ++q;
+           }
+           else
+               intsize = 'h';
+           break;
        case 'V':
+       case 'z':
+       case 't':
+#if HAS_C99
+        case 'j':
+#endif
            intsize = *q++;
            break;
        }
@@ -10382,10 +10452,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            }
            else if (args) {
                switch (intsize) {
+               case 'c':       iv = (char)va_arg(*args, int); break;
                case 'h':       iv = (short)va_arg(*args, int); break;
                case 'l':       iv = va_arg(*args, long); break;
                case 'V':       iv = va_arg(*args, IV); break;
+               case 'z':       iv = va_arg(*args, SSize_t); break;
+               case 't':       iv = va_arg(*args, ptrdiff_t); break;
                default:        iv = va_arg(*args, int); break;
+#if HAS_C99
+               case 'j':       iv = va_arg(*args, intmax_t); break;
+#endif
                case 'q':
 #ifdef HAS_QUAD
                                iv = va_arg(*args, Quad_t); break;
@@ -10397,6 +10473,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            else {
                IV tiv = SvIV(argsv); /* work around GCC bug #13488 */
                switch (intsize) {
+               case 'c':       iv = (char)tiv; break;
                case 'h':       iv = (short)tiv; break;
                case 'l':       iv = (long)tiv; break;
                case 'V':
@@ -10473,9 +10550,15 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            }
            else if (args) {
                switch (intsize) {
+               case 'c':  uv = (unsigned char)va_arg(*args, unsigned); break;
                case 'h':  uv = (unsigned short)va_arg(*args, unsigned); break;
                case 'l':  uv = va_arg(*args, unsigned long); break;
                case 'V':  uv = va_arg(*args, UV); break;
+               case 'z':  uv = va_arg(*args, Size_t); break;
+               case 't':  uv = va_arg(*args, ptrdiff_t); break; /* will sign extend, but there is no uptrdiff_t, so oh well */
+#if HAS_C99
+               case 'j':  uv = va_arg(*args, uintmax_t); break;
+#endif
                default:   uv = va_arg(*args, unsigned); break;
                case 'q':
 #ifdef HAS_QUAD
@@ -10488,6 +10571,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            else {
                UV tuv = SvUV(argsv); /* work around GCC bug #13488 */
                switch (intsize) {
+               case 'c':       uv = (unsigned char)tuv; break;
                case 'h':       uv = (unsigned short)tuv; break;
                case 'l':       uv = (unsigned long)tuv; break;
                case 'V':
@@ -10598,7 +10682,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
 #else
                /*FALLTHROUGH*/
 #endif
+           case 'c':
            case 'h':
+           case 'z':
+           case 't':
+           case 'j':
                goto unknown;
            }
 
@@ -10778,10 +10866,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            i = SvCUR(sv) - origlen;
            if (args) {
                switch (intsize) {
+               case 'c':       *(va_arg(*args, char*)) = i; break;
                case 'h':       *(va_arg(*args, short*)) = i; break;
                default:        *(va_arg(*args, int*)) = i; break;
                case 'l':       *(va_arg(*args, long*)) = i; break;
                case 'V':       *(va_arg(*args, IV*)) = i; break;
+               case 'z':       *(va_arg(*args, SSize_t*)) = i; break;
+               case 't':       *(va_arg(*args, ptrdiff_t*)) = i; break;
+#if HAS_C99
+               case 'j':       *(va_arg(*args, intmax_t*)) = i; break;
+#endif
                case 'q':
 #ifdef HAS_QUAD
                                *(va_arg(*args, Quad_t*)) = i; break;
@@ -11527,7 +11621,7 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa
            SvPV_set(dstr, SAVEPVN(SvPVX_const(sstr), SvLEN(sstr)-1));
            if (SvREADONLY(sstr) && SvFAKE(sstr)) {
                /* Not that normal - actually sstr is copy on write.
-                  But we are a true, independant SV, so:  */
+                  But we are a true, independent SV, so:  */
                SvREADONLY_off(dstr);
                SvFAKE_off(dstr);
            }
@@ -12030,7 +12124,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
                ncx->blk_loop.state_u.lazysv.end
                    = sv_dup_inc(ncx->blk_loop.state_u.lazysv.end, param);
                /* We are taking advantage of av_dup_inc and sv_dup_inc
-                  actually being the same function, and order equivalance of
+                  actually being the same function, and order equivalence of
                   the two unions.
                   We can assert the later [but only at run time :-(]  */
                assert ((void *) &ncx->blk_loop.state_u.ary.ary ==
@@ -14009,6 +14103,12 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
                if ( (type == OP_CONST && SvOK(cSVOPx_sv(kid)))
                  || (type == OP_NULL  && ! (kid->op_flags & OPf_KIDS))
                  || (type == OP_PUSHMARK)
+                 || (
+                     /* @$a and %$a, but not @a or %a */
+                       (type == OP_RV2AV || type == OP_RV2HV)
+                    && cUNOPx(kid)->op_first
+                    && cUNOPx(kid)->op_first->op_type != OP_GV
+                    )
                )
                continue;
            }