This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
remove vestigial uses of PRIVSHIFT
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index bb2cc21..e3e5af4 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1525,7 +1525,11 @@ wrapper instead.
 =cut
 */
 
-int
+/* prior to 5.000 stable, this function returned the new OOK-less SvFLAGS
+   prior to 5.23.4 this function always returned 0
+*/
+
+void
 Perl_sv_backoff(SV *const sv)
 {
     STRLEN delta;
@@ -1541,9 +1545,9 @@ Perl_sv_backoff(SV *const sv)
     
     SvLEN_set(sv, SvLEN(sv) + delta);
     SvPV_set(sv, SvPVX(sv) - delta);
-    Move(s, SvPVX(sv), SvCUR(sv)+1, char);
     SvFLAGS(sv) &= ~SVf_OOK;
-    return 0;
+    Move(s, SvPVX(sv), SvCUR(sv)+1, char);
+    return;
 }
 
 /*
@@ -5753,10 +5757,9 @@ S_sv_unmagicext_flags(pTHX_ SV *const sv, const int type, MGVTBL *vtbl, const U3
        if (SvMAGICAL(sv))      /* if we're under save_magic, wait for restore_magic; */
            mg_magical(sv);     /*    else fix the flags now */
     }
-    else {
+    else
        SvMAGICAL_off(sv);
-       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
-    }
+
     return 0;
 }
 
@@ -6838,7 +6841,7 @@ Perl_sv_newref(pTHX_ SV *const sv)
 
 Decrement an SV's reference count, and if it drops to zero, call
 C<sv_clear> to invoke destructors and free up any memory used by
-the body; finally, deallocate the SV's head itself.
+the body; finally, deallocating the SV's head itself.
 Normally called via a wrapper macro C<SvREFCNT_dec>.
 
 =cut
@@ -8769,6 +8772,10 @@ Perl_sv_inc_nomg(pTHX_ SV *const sv)
        return;
     }
 
+    /* treat AV/HV/CV/FM/IO and non-fake GVs as immutable */
+    if (SvTYPE(sv) >= SVt_PVAV || (isGV_with_GP(sv) && !SvFAKE(sv)))
+        Perl_croak_no_modify();
+
     if (!(flags & SVp_POK) || !*SvPVX_const(sv)) {
        if ((flags & SVTYPEMASK) < SVt_PVIV)
            sv_upgrade(sv, ((flags & SVTYPEMASK) > SVt_IV ? SVt_PVIV : SVt_IV));
@@ -8948,6 +8955,11 @@ Perl_sv_dec_nomg(pTHX_ SV *const sv)
            return;
        }
     }
+
+    /* treat AV/HV/CV/FM/IO and non-fake GVs as immutable */
+    if (SvTYPE(sv) >= SVt_PVAV || (isGV_with_GP(sv) && !SvFAKE(sv)))
+        Perl_croak_no_modify();
+
     if (!(flags & SVp_POK)) {
        if ((flags & SVTYPEMASK) < SVt_PVIV)
            sv_upgrade(sv, ((flags & SVTYPEMASK) > SVt_IV) ? SVt_PVIV : SVt_IV);
@@ -9929,6 +9941,9 @@ Perl_sv_pvutf8n_force(pTHX_ SV *const sv, STRLEN *const lp)
 
 Returns a string describing what the SV is a reference to.
 
+If ob is true and the SV is blessed, the string is the class name,
+otherwise it is the type of the SV, "SCALAR", "ARRAY" etc.
+
 =cut
 */
 
@@ -9987,6 +10002,12 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 
 Returns a SV describing what the SV passed in is a reference to.
 
+dst can be a SV to be set to the description or NULL, in which case a
+mortal SV is returned.
+
+If ob is true and the SV is blessed, the description is the class
+name, otherwise it is the type of the SV, "SCALAR", "ARRAY" etc.
+
 =cut
 */
 
@@ -11444,9 +11465,10 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                   is safe. */
                is_utf8 = (bool)va_arg(*args, int);
                elen = va_arg(*args, UV);
-                if ((IV)elen < 0) {
-                    /* check if utf8 length is larger than 0 when cast to IV */
-                    assert( (IV)elen >= 0 ); /* in DEBUGGING build we want to crash */
+                /* if utf8 length is larger than 0x7ffff..., then it might
+                 * have been a signed value that wrapped */
+                if (elen  > ((~(STRLEN)0) >> 1)) {
+                    assert(0); /* in DEBUGGING build we want to crash */
                     elen= 0; /* otherwise we want to treat this as an empty string */
                 }
                eptr = va_arg(*args, char *);
@@ -12309,6 +12331,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 U8* v = vhex; /* working pointer to vhex */
                 U8* vend; /* pointer to one beyond last digit of vhex */
                 U8* vfnz = NULL; /* first non-zero */
+                U8* vlnz = NULL; /* last non-zero */
                 const bool lower = (c == 'a');
                 /* At output the values of vhex (up to vend) will
                  * be mapped through the xdig to get the actual
@@ -12316,6 +12339,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 const char* xdig = PL_hexdigit;
                 int zerotail = 0; /* how many extra zeros to append */
                 int exponent = 0; /* exponent of the floating point input */
+                bool hexradix = FALSE; /* should we output the radix */
 
                 /* XXX: denormals, NaN, Inf.
                  *
@@ -12340,7 +12364,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
 #  endif
 #endif
 
-                if (fv < 0)
+                if (fv < 0
+                    || Perl_signbit(nv)
+                  )
                     *p++ = '-';
                 else if (plus)
                     *p++ = plus;
@@ -12362,8 +12388,6 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 }
 
                 if (vfnz) {
-                    U8* vlnz = NULL; /* The last non-zero. */
-
                     /* Find the last non-zero xdigit. */
                     for (v = vend - 1; v >= vhex; v--) {
                         if (*v) {
@@ -12423,9 +12447,24 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                     v = vhex;
                     *p++ = xdig[*v++];
 
-                    /* The radix is always output after the first
-                     * non-zero xdigit, or if alt.  */
-                    if (vfnz < vlnz || alt) {
+                    /* If there are non-zero xdigits, the radix
+                     * is output after the first one. */
+                    if (vfnz < vlnz) {
+                      hexradix = TRUE;
+                    }
+                }
+                else {
+                    *p++ = '0';
+                    exponent = 0;
+                    zerotail = precis;
+                }
+
+                /* The radix is always output if precis, or if alt. */
+                if (precis > 0 || alt) {
+                  hexradix = TRUE;
+                }
+
+                if (hexradix) {
 #ifndef USE_LOCALE_NUMERIC
                         *p++ = '.';
 #else
@@ -12441,17 +12480,17 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                         }
                         RESTORE_LC_NUMERIC();
 #endif
-                    }
+                }
 
+                if (vlnz) {
                     while (v <= vlnz)
                         *p++ = xdig[*v++];
-
-                    while (zerotail--)
-                        *p++ = '0';
                 }
-                else {
+
+                if (zerotail > 0) {
+                  while (zerotail--) {
                     *p++ = '0';
-                    exponent = 0;
+                  }
                 }
 
                 elen = p - PL_efloatbuf;
@@ -12562,7 +12601,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                     elen = quadmath_snprintf(PL_efloatbuf, PL_efloatsize,
                                              qfmt, nv);
                     if ((IV)elen == -1)
-                        Perl_croak_nocontext("panic: quadmath_snprintf failed, format \"%s|'", qfmt);
+                        Perl_croak_nocontext("panic: quadmath_snprintf failed, format \"%s\"", qfmt);
                     if (qfmt != ptr)
                         Safefree(qfmt);
                 }
@@ -12690,7 +12729,8 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
            }
        }
 
-        assert((IV)elen >= 0); /* here zero elen is fine */
+        /* signed value that's wrapped? */
+        assert(elen  <= ((~(STRLEN)0) >> 1));
        have = esignlen + zeros + elen;
        if (have < zeros)
            croak_memory_wrap();
@@ -12931,7 +12971,11 @@ Perl_fp_dup(pTHX_ PerlIO *const fp, const char type, CLONE_PARAMS *const param)
        return ret;
 
     /* create anew and remember what it is */
+#ifdef __amigaos4__
+    ret = PerlIO_fdupopen(aTHX_ fp, param, PERLIO_DUP_CLONE|PERLIO_DUP_FD);
+#else
     ret = PerlIO_fdupopen(aTHX_ fp, param, PERLIO_DUP_CLONE);
+#endif
     ptr_table_store(PL_ptr_table, fp, ret);
     return ret;
 }
@@ -14404,9 +14448,11 @@ perl_clone(PerlInterpreter *proto_perl, UV flags)
    /* perlhost.h so we need to call into it
    to clone the host, CPerlHost should have a c interface, sky */
 
+#ifndef __amigaos4__
    if (flags & CLONEf_CLONE_HOST) {
        return perl_clone_host(proto_perl,flags);
    }
+#endif
    return perl_clone_using(proto_perl, flags,
                            proto_perl->IMem,
                            proto_perl->IMemShared,
@@ -15286,7 +15332,7 @@ will be converted into Unicode (and UTF-8).
 If C<sv> already is UTF-8 (or if it is not C<POK>), or if C<encoding>
 is not a reference, nothing is done to C<sv>.  If C<encoding> is not
 an C<Encode::XS> Encoding object, bad things will happen.
-(See F<lib/encoding.pm> and L<Encode>.)
+(See F<cpan/Encode/encoding.pm> and L<Encode>.)
 
 The PV of C<sv> is returned.
 
@@ -15359,7 +15405,7 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
 C<encoding> is assumed to be an C<Encode> object, the PV of C<ssv> is
 assumed to be octets in that encoding and decoding the input starts
 from the position which S<C<(PV + *offset)>> pointed to.  C<dsv> will be
-concatenated the decoded UTF-8 string from C<ssv>.  Decoding will terminate
+concatenated with the decoded UTF-8 string from C<ssv>.  Decoding will terminate
 when the string C<tstr> appears in decoding output or the input ends on
 the PV of C<ssv>.  The value which C<offset> points will be modified
 to the last input position on C<ssv>.