[5.004_61 PATCH] Make incompatible changes to RE engine NOW
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index 1ab0e31..b5bec9d 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -59,6 +59,8 @@ static void sv_mortalgrow _((void));
 static void sv_unglob _((SV* sv));
 static void sv_check_thinkfirst _((SV *sv));
 
+#define SV_CHECK_THINKFIRST(sv) if (SvTHINKFIRST(sv)) sv_check_thinkfirst(sv)
+
 #ifndef PURIFY
 static void *my_safemalloc(MEM_SIZE size);
 #endif
@@ -1085,6 +1087,10 @@ sv_grow(SV* sv, unsigned long newlen)
        s = SvPVX(sv);
        if (newlen > SvLEN(sv))
            newlen += 10 * (newlen - SvCUR(sv)); /* avoid copy each time */
+#ifdef HAS_64K_LIMIT
+       if (newlen >= 0x10000)
+           newlen = 0xFFFF;
+#endif
     }
     else
        s = SvPVX(sv);
@@ -1102,7 +1108,7 @@ sv_grow(SV* sv, unsigned long newlen)
 void
 sv_setiv(register SV *sv, IV i)
 {
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
        sv_upgrade(sv, SVt_IV);
@@ -1163,13 +1169,12 @@ sv_setuv_mg(register SV *sv, UV u)
 void
 sv_setnv(register SV *sv, double num)
 {
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
     case SVt_IV:
        sv_upgrade(sv, SVt_NV);
        break;
-    case SVt_NV:
     case SVt_RV:
     case SVt_PV:
     case SVt_PVIV:
@@ -1716,8 +1721,7 @@ sv_2pv(register SV *sv, STRLEN *lp)
            return "";
        }
     }
-    if (!SvUPGRADE(sv, SVt_PV))
-       return 0;
+    (void)SvUPGRADE(sv, SVt_PV);
     if (SvNOKp(sv)) {
        if (SvTYPE(sv) < SVt_PVNV)
            sv_upgrade(sv, SVt_PVNV);
@@ -1867,7 +1871,7 @@ sv_setsv(SV *dstr, register SV *sstr)
 
     if (sstr == dstr)
        return;
-    sv_check_thinkfirst(dstr);
+    SV_CHECK_THINKFIRST(dstr);
     if (!sstr)
        sstr = &sv_undef;
     stype = SvTYPE(sstr);
@@ -1935,7 +1939,6 @@ sv_setsv(SV *dstr, register SV *sstr)
        if (dtype < SVt_PVNV)
            sv_upgrade(dstr, SVt_PVNV);
        break;
-
     case SVt_PVAV:
     case SVt_PVHV:
     case SVt_PVCV:
@@ -1986,8 +1989,10 @@ sv_setsv(SV *dstr, register SV *sstr)
                    goto glob_assign;
            }
        }
-       if (dtype < stype)
-           sv_upgrade(dstr, stype);
+       if (stype == SVt_PVLV)
+           SvUPGRADE(dstr, SVt_PVNV);
+       else
+           SvUPGRADE(dstr, stype);
     }
 
     sflags = SvFLAGS(sstr);
@@ -2058,9 +2063,14 @@ sv_setsv(SV *dstr, register SV *sstr)
                                if (cv_const_sv(cv))
                                    warn("Constant subroutine %s redefined",
                                         GvENAME((GV*)dstr));
-                               else if (dowarn)
-                                   warn("Subroutine %s redefined",
-                                        GvENAME((GV*)dstr));
+                               else if (dowarn) {
+                                   if (!(CvGV(cv) && GvSTASH(CvGV(cv))
+                                         && HvNAME(GvSTASH(CvGV(cv)))
+                                         && strEQ(HvNAME(GvSTASH(CvGV(cv))),
+                                                  "autouse")))
+                                       warn("Subroutine %s redefined",
+                                            GvENAME((GV*)dstr));
+                               }
                            }
                            cv_ckproto(cv, (GV*)dstr,
                                       SvPOK(sref) ? SvPVX(sref) : Nullch);
@@ -2199,9 +2209,10 @@ sv_setsv_mg(SV *dstr, register SV *sstr)
 void
 sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
 {
+    register char *dptr;
     assert(len >= 0);  /* STRLEN is probably unsigned, so this may
                          elicit a warning, but it won't hurt. */
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (!ptr) {
        (void)SvOK_off(sv);
        return;
@@ -2210,12 +2221,14 @@ sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
        if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
            sv_unglob(sv);
     }
-    else if (!sv_upgrade(sv, SVt_PV))
-       return;
+    else
+       sv_upgrade(sv, SVt_PV);
+
     SvGROW(sv, len + 1);
-    Move(ptr,SvPVX(sv),len,char);
+    dptr = SvPVX(sv);
+    Move(ptr,dptr,len,char);
+    dptr[len] = '\0';
     SvCUR_set(sv, len);
-    *SvEND(sv) = '\0';
     (void)SvPOK_only(sv);              /* validate pointer */
     SvTAINT(sv);
 }
@@ -2232,7 +2245,7 @@ sv_setpv(register SV *sv, register const char *ptr)
 {
     register STRLEN len;
 
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (!ptr) {
        (void)SvOK_off(sv);
        return;
@@ -2242,8 +2255,9 @@ sv_setpv(register SV *sv, register const char *ptr)
        if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
            sv_unglob(sv);
     }
-    else if (!sv_upgrade(sv, SVt_PV))
-       return;
+    else 
+       sv_upgrade(sv, SVt_PV);
+
     SvGROW(sv, len + 1);
     Move(ptr,SvPVX(sv),len+1,char);
     SvCUR_set(sv, len);
@@ -2261,9 +2275,8 @@ sv_setpv_mg(register SV *sv, register const char *ptr)
 void
 sv_usepvn(register SV *sv, register char *ptr, register STRLEN len)
 {
-    sv_check_thinkfirst(sv);
-    if (!SvUPGRADE(sv, SVt_PV))
-       return;
+    SV_CHECK_THINKFIRST(sv);
+    (void)SvUPGRADE(sv, SVt_PV);
     if (!ptr) {
        (void)SvOK_off(sv);
        return;
@@ -2282,22 +2295,20 @@ sv_usepvn(register SV *sv, register char *ptr, register STRLEN len)
 void
 sv_usepvn_mg(register SV *sv, register char *ptr, register STRLEN len)
 {
-    sv_usepvn_mg(sv,ptr,len);
+    sv_usepvn(sv,ptr,len);
     SvSETMAGIC(sv);
 }
 
 static void
 sv_check_thinkfirst(register SV *sv)
 {
-    if (SvTHINKFIRST(sv)) {
-       if (SvREADONLY(sv)) {
-           dTHR;
-           if (curcop != &compiling)
-               croak(no_modify);
-       }
-       if (SvROK(sv))
-           sv_unref(sv);
+    if (SvREADONLY(sv)) {
+       dTHR;
+       if (curcop != &compiling)
+           croak(no_modify);
     }
+    if (SvROK(sv))
+       sv_unref(sv);
 }
     
 void
@@ -2309,7 +2320,7 @@ sv_chop(register SV *sv, register char *ptr)      /* like set but assuming ptr is in
 
     if (!ptr || !SvPOKp(sv))
        return;
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (SvTYPE(sv) < SVt_PVIV)
        sv_upgrade(sv,SVt_PVIV);
 
@@ -2390,7 +2401,7 @@ sv_catpv(register SV *sv, register char *ptr)
 void
 sv_catpv_mg(register SV *sv, register char *ptr)
 {
-    sv_catpv_mg(sv,ptr);
+    sv_catpv(sv,ptr);
     SvSETMAGIC(sv);
 }
 
@@ -2434,8 +2445,7 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
        }
     }
     else {
-       if (!SvUPGRADE(sv, SVt_PVMG))
-           return;
+        (void)SvUPGRADE(sv, SVt_PVMG);
     }
     Newz(702,mg, 1, MAGIC);
     mg->mg_moremagic = SvMAGIC(sv);
@@ -2683,7 +2693,7 @@ void
 sv_replace(register SV *sv, register SV *nsv)
 {
     U32 refcnt = SvREFCNT(sv);
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (SvREFCNT(nsv) != 1)
        warn("Reference miscount in sv_replace()");
     if (SvMAGICAL(sv)) {
@@ -2866,13 +2876,15 @@ SV *
 sv_newref(SV *sv)
 {
     if (sv)
-       SvREFCNT(sv)++;
+       ATOMIC_INC(SvREFCNT(sv));
     return sv;
 }
 
 void
 sv_free(SV *sv)
 {
+    int refcount_is_zero;
+
     if (!sv)
        return;
     if (SvREADONLY(sv)) {
@@ -2887,7 +2899,8 @@ sv_free(SV *sv)
        warn("Attempt to free unreferenced scalar");
        return;
     }
-    if (--SvREFCNT(sv) > 0)
+    ATOMIC_DEC_AND_TEST(refcount_is_zero, SvREFCNT(sv));
+    if (!refcount_is_zero)
        return;
 #ifdef DEBUGGING
     if (SvTEMP(sv)) {
@@ -3080,9 +3093,8 @@ sv_gets(register SV *sv, register PerlIO *fp, I32 append)
     register I32 cnt;
     I32 i;
 
-    sv_check_thinkfirst(sv);
-    if (!SvUPGRADE(sv, SVt_PV))
-       return 0;
+    SV_CHECK_THINKFIRST(sv);
+    (void)SvUPGRADE(sv, SVt_PV);
     SvSCREAM_off(sv);
 
     if (RsSNARF(rs)) {
@@ -3987,7 +3999,7 @@ newSVrv(SV *rv, char *classname)
     SvREFCNT(sv) = 0;
     SvFLAGS(sv) = 0;
 
-    sv_check_thinkfirst(rv);
+    SV_CHECK_THINKFIRST(rv);
 #ifdef OVERLOAD
     SvAMAGIC_off(rv);
 #endif /* OVERLOAD */
@@ -4566,6 +4578,8 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
            switch (base) {
                unsigned dig;
            case 16:
+               if (!uv)
+                   alt = FALSE;
                p = (c == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
                do {
                    dig = uv & 15;
@@ -4592,8 +4606,12 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
                break;
            }
            elen = (ebuf + sizeof ebuf) - eptr;
-           if (has_precis && precis > elen)
-               zeros = precis - elen;
+           if (has_precis) {
+               if (precis > elen)
+                   zeros = precis - elen;
+               else if (precis == 0 && elen == 1 && *eptr == '0')
+                   elen = 0;
+           }
            break;
 
            /* FLOATING POINT */