Regen stuff.
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index dd35da7..1c1932a 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -4462,10 +4462,12 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
        each other.  To prevent a reference loop that would prevent such
        objects being freed, we look for such loops and if we find one we
        avoid incrementing the object refcount.
+
        Note we cannot do this to avoid self-tie loops as intervening RV must
-       have its REFCNT incremented to keep it in existence - instead special
-       case them in sv_free().
-     */
+       have its REFCNT incremented to keep it in existence - instead we could
+       special case them in sv_free() -- NI-S
+
+    */
     if (!obj || obj == sv ||
        how == PERL_MAGIC_arylen ||
        how == PERL_MAGIC_qr ||
@@ -5171,23 +5173,8 @@ Perl_sv_free(pTHX_ SV *sv)
        return;
     }
     ATOMIC_DEC_AND_TEST(refcount_is_zero, SvREFCNT(sv));
-    if (!refcount_is_zero) {
-       if (SvREFCNT(sv) == 1) {
-           /* Break self-tie loops */
-           MAGIC *mg = 0;
-           SV *obj;
-           if (SvTYPE(sv) == SVt_PVGV)
-               sv = (SV *)GvIO(sv);
-           if (!sv || !SvMAGICAL(sv) || SvTYPE(sv) < SVt_PVMG)
-               return;
-            mg = SvTIED_mg(sv, PERL_MAGIC_tiedscalar);
-           if (mg && (obj = mg->mg_obj) && SvROK(obj) &&
-               (SvRV(obj) == sv || GvIO(SvRV(obj)) == (IO *) sv)) {
-               sv_unmagic(sv, PERL_MAGIC_tiedscalar);
-           }
-       }
+    if (!refcount_is_zero)
        return;
-    }
 #ifdef DEBUGGING
     if (SvTEMP(sv)) {
        if (ckWARN_d(WARN_DEBUGGING))
@@ -5895,13 +5882,15 @@ screamer2:
            /* Accomodate broken VAXC compiler, which applies U8 cast to
             * both args of ?: operator, causing EOF to change into 255
             */
-           if (cnt) { i = (U8)buf[cnt - 1]; } else { i = EOF; }
+           if (cnt > 0) { i = (U8)buf[cnt - 1]; } else { i = EOF; }
        }
 
-       if (append)
-           sv_catpvn(sv, (char *) buf, cnt);
-       else
-           sv_setpvn(sv, (char *) buf, cnt);
+       if (cnt > 0) {
+           if (append)
+               sv_catpvn(sv, (char *) buf, cnt);
+           else
+               sv_setpvn(sv, (char *) buf, cnt);
+       }
 
        if (i != EOF &&                 /* joy */
            (!rslen ||
@@ -6230,6 +6219,7 @@ SV *
 Perl_sv_mortalcopy(pTHX_ SV *oldstr)
 {
     register SV *sv;
+
     new_SV(sv);
     sv_setsv(sv,oldstr);
     EXTEND_MORTAL(1);
@@ -7750,7 +7740,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        unsigned base = 0;
        IV iv = 0;
        UV uv = 0;
+       /* we need a long double target in case HAS_LONG_DOUBLE but
+          not USE_LONG_DOUBLE
+       */
+#if defined(HAS_LONG_DOUBLE) && LONG_DOUBLESIZE > DOUBLESIZE
+       long double nv;
+#else
        NV nv;
+#endif
        STRLEN have;
        STRLEN need;
        STRLEN gap;
@@ -7926,18 +7923,18 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            q++;
            break;
 #endif
-#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE))
+#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
        case 'L':                       /* Ld */
            /* FALL THROUGH */
-#endif
 #ifdef HAS_QUAD
        case 'q':                       /* qd */
+#endif
            intsize = 'q';
            q++;
            break;
 #endif
        case 'l':
-#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE))
+#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
              if (*(q + 1) == 'l') {    /* lld, llf */
                intsize = 'q';
                q += 2;
@@ -8254,11 +8251,49 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* This is evil, but floating point is even more evil */
 
            vectorize = FALSE;
-           nv = args ? va_arg(*args, NV) : SvNVx(argsv);
+           /* for SV-style calling, we can only get NV
+              for C-style calling, we assume %f is double;
+              for simplicity we allow any of %Lf, %llf, %qf for long double
+           */
+           switch (intsize) {
+           case 'V':
+#if defined(USE_LONG_DOUBLE)
+               intsize = 'q';
+#endif
+               break;
+           default:
+#if defined(USE_LONG_DOUBLE)
+               intsize = args ? 0 : 'q';
+#endif
+               break;
+           case 'q':
+#if defined(HAS_LONG_DOUBLE)
+               break;
+#else
+               /* FALL THROUGH */
+#endif
+           case 'h':
+               /* FALL THROUGH */
+           case 'l':
+               goto unknown;
+           }
+
+           /* now we need (long double) if intsize == 'q', else (double) */
+           nv = args ?
+#if LONG_DOUBLESIZE > DOUBLESIZE
+               intsize == 'q' ?
+                   va_arg(*args, long double) :
+                   va_arg(*args, double)
+#else
+                   va_arg(*args, double)
+#endif
+               : SvNVx(argsv);
 
            need = 0;
            if (c != 'e' && c != 'E') {
                i = PERL_INT_MIN;
+               /* FIXME: if HAS_LONG_DOUBLE but not USE_LONG_DOUBLE this
+                  will cast our (long double) to (double) */
                (void)Perl_frexp(nv, &i);
                if (i == PERL_INT_MIN)
                    Perl_die(aTHX_ "panic: frexp");
@@ -8280,8 +8315,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            eptr = ebuf + sizeof ebuf;
            *--eptr = '\0';
            *--eptr = c;
-#if defined(USE_LONG_DOUBLE) && defined(PERL_PRIfldbl)
-           {
+           /* FIXME: what to do if HAS_LONG_DOUBLE but not PERL_PRIfldbl? */
+#if defined(HAS_LONG_DOUBLE) && defined(PERL_PRIfldbl)
+           if (intsize == 'q') {
                /* Copy the one or more characters in a long double
                 * format before the 'base' ([efgEFG]) character to
                 * the format string. */
@@ -8312,8 +8348,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* No taint.  Otherwise we are in the strange situation
             * where printf() taints but print($float) doesn't.
             * --jhi */
+#if defined(HAS_LONG_DOUBLE)
+           if (intsize == 'q')
+               (void)sprintf(PL_efloatbuf, eptr, nv);
+           else
+               (void)sprintf(PL_efloatbuf, eptr, (double)nv);
+#else
            (void)sprintf(PL_efloatbuf, eptr, nv);
-
+#endif
            eptr = PL_efloatbuf;
            elen = strlen(PL_efloatbuf);
            break;
@@ -8769,7 +8811,6 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv)
     for (tblent = *otblent; tblent; i=0, tblent = tblent->next) {
        if (tblent->oldval == oldv) {
            tblent->newval = newv;
-           tbl->tbl_items++;
            return;
        }
     }
@@ -8871,10 +8912,10 @@ char *PL_watch_pvx;
 /* attempt to make everything in the typeglob readonly */
 
 STATIC SV *
-S_gv_share(pTHX_ SV *sstr)
+S_gv_share(pTHX_ SV *sstr, CLONE_PARAMS *param)
 {
     GV *gv = (GV*)sstr;
-    SV *sv = &PL_sv_no; /* just need SvREADONLY-ness */
+    SV *sv = &param->proto_perl->Isv_no; /* just need SvREADONLY-ness */
 
     if (GvIO(gv) || GvFORM(gv)) {
         GvUNIQUE_off(gv); /* GvIOs cannot be shared. nor can GvFORMs */
@@ -8884,7 +8925,7 @@ S_gv_share(pTHX_ SV *sstr)
     }
     else {
         /* CvPADLISTs cannot be shared */
-        if (!CvXSUB(GvCV(gv))) {
+        if (!SvREADONLY(GvCV(gv)) && !CvXSUB(GvCV(gv))) {
             GvUNIQUE_off(gv);
         }
     }
@@ -9065,9 +9106,10 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
     case SVt_PVGV:
        if (GvUNIQUE((GV*)sstr)) {
             SV *share;
-            if ((share = gv_share(sstr))) {
+            if ((share = gv_share(sstr, param))) {
                 del_SV(dstr);
                 dstr = share;
+                ptr_table_store(PL_ptr_table, sstr, dstr);
 #if 0
                 PerlIO_printf(Perl_debug_log, "sv_dup: sharing %s::%s\n",
                               HvNAME(GvSTASH(share)), GvNAME(share));
@@ -9302,7 +9344,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
            case CXt_EVAL:
                ncx->blk_eval.old_in_eval = cx->blk_eval.old_in_eval;
                ncx->blk_eval.old_op_type = cx->blk_eval.old_op_type;
-               ncx->blk_eval.old_namesv = sv_dup_inc(cx->blk_eval.old_namesv, param);;
+               ncx->blk_eval.old_namesv = sv_dup_inc(cx->blk_eval.old_namesv, param);
                ncx->blk_eval.old_eval_root = cx->blk_eval.old_eval_root;
                ncx->blk_eval.cur_text  = sv_dup(cx->blk_eval.cur_text, param);
                break;
@@ -9770,6 +9812,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 #    endif     /* DEBUGGING */
 #endif         /* PERL_IMPLICIT_SYS */
     param->flags = flags;
+    param->proto_perl = proto_perl;
 
     /* arena roots */
     PL_xiv_arenaroot   = NULL;