This is 5.8.0.
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index 7d51f32..fe7c0d4 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 ||
@@ -4479,15 +4481,6 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
     else {
        mg->mg_obj = SvREFCNT_inc(obj);
        mg->mg_flags |= MGf_REFCOUNTED;
-
-       /* Break self-tie loops */
-       if (how == PERL_MAGIC_tiedscalar && SvROK(obj) &&
-          (SvRV(obj) == sv || GvIO(SvRV(obj)) == (IO *) sv)) {
-           /* We have to have a REFCNT to obj, so drop REFCNT
-              of what if references instead
-            */
-           SvREFCNT_dec(SvRV(obj));
-       }
     }
     mg->mg_type = how;
     mg->mg_len = namlen;
@@ -5180,12 +5173,8 @@ Perl_sv_free(pTHX_ SV *sv)
        return;
     }
     ATOMIC_DEC_AND_TEST(refcount_is_zero, SvREFCNT(sv));
-    if (!refcount_is_zero) {
-       /* Do not be tempted to test SvMAGIC here till scope.c
-          stops sharing MAGIC * between SVs
-        */
+    if (!refcount_is_zero)
        return;
-    }
 #ifdef DEBUGGING
     if (SvTEMP(sv)) {
        if (ckWARN_d(WARN_DEBUGGING))
@@ -5324,9 +5313,11 @@ Perl_sv_pos_b2u(pTHX_ register SV *sv, I32* offsetp)
     send = s + *offsetp;
     len = 0;
     while (s < send) {
-       STRLEN n;
-       /* Call utf8n_to_uvchr() to validate the sequence */
-       utf8n_to_uvchr(s, UTF8SKIP(s), &n, 0);
+       STRLEN n = 1;
+       /* Call utf8n_to_uvchr() to validate the sequence
+        * (unless a simple non-UTF character) */
+       if (!UTF8_IS_INVARIANT(*s))
+           utf8n_to_uvchr(s, UTF8SKIP(s), &n, 0);
        if (n > 0) {
            s += n;
            len++;
@@ -5893,13 +5884,18 @@ 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 (cnt < 0)
+           cnt = 0;  /* we do need to re-set the sv even when cnt <= 0 */
        if (append)
-           sv_catpvn(sv, (char *) buf, cnt);
+            sv_catpvn(sv, (char *) buf, cnt);
        else
-           sv_setpvn(sv, (char *) buf, cnt);
+            sv_setpvn(sv, (char *) buf, cnt);
 
        if (i != EOF &&                 /* joy */
            (!rslen ||
@@ -6228,6 +6224,7 @@ SV *
 Perl_sv_mortalcopy(pTHX_ SV *oldstr)
 {
     register SV *sv;
+
     new_SV(sv);
     sv_setsv(sv,oldstr);
     EXTEND_MORTAL(1);
@@ -7740,7 +7737,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
         /* large enough for "%#.#f" --chip */
        /* what about long double NVs? --jhi */
 
-       SV *vecsv;
+       SV *vecsv = Nullsv;
        U8 *vecstr = Null(U8*);
        STRLEN veclen = 0;
        char c = 0;
@@ -7748,7 +7745,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;
@@ -7773,7 +7777,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     We allow format specification elements in this order:
        \d+\$              explicit format parameter index
        [-+ 0#]+           flags
-       \*?(\d+\$)?v       vector with optional (optionally specified) arg
+       v|\*(\d+\$)?v      vector with optional (optionally specified) arg
        \d+|\*(\d+\$)?     width using optional (optionally specified) arg
        \.(\d*|\*(\d+\$)?) precision using optional (optionally specified) arg
        [hlqLV]            size
@@ -7885,7 +7889,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            q++;
            if (*q == '*') {
                q++;
-               if (EXPECT_NUMBER(q, epix) && *q++ != '$') /* epix currently unused */
+               if (EXPECT_NUMBER(q, epix) && *q++ != '$')
+                   goto unknown;
+               /* XXX: todo, support specified precision parameter */
+               if (epix)
                    goto unknown;
                if (args)
                    i = va_arg(*args, int);
@@ -7924,18 +7931,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;
@@ -7958,7 +7965,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
        }
 
-       if (!args)
+       if (vectorize)
+           argsv = vecsv;
+       else if (!args)
            argsv = (efix ? efix <= svmax : svix < svmax) ?
                    svargs[efix ? efix-1 : svix++] : &PL_sv_undef;
 
@@ -7967,7 +7976,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* STRINGS */
 
        case 'c':
-           uv = args ? va_arg(*args, int) : SvIVx(argsv);
+           uv = (args && !vectorize) ? va_arg(*args, int) : SvIVx(argsv);
            if ((uv > 255 ||
                 (!UNI_IS_INVARIANT(uv) && SvUTF8(sv)))
                && !IN_BYTES) {
@@ -7983,7 +7992,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
 
        case 's':
-           if (args) {
+           if (args && !vectorize) {
                eptr = va_arg(*args, char*);
                if (eptr)
 #ifdef MACOS_TRADITIONAL
@@ -8020,7 +8029,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
             * if ISO or ANSI decide to use '_' for something.
             * So we keep it hidden from users' code.
             */
-           if (!args)
+           if (!args || vectorize)
                goto unknown;
            argsv = va_arg(*args, SV*);
            eptr = SvPVx(argsv, elen);
@@ -8036,7 +8045,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* INTEGERS */
 
        case 'p':
-           if (alt)
+           if (alt || vectorize)
                goto unknown;
            uv = PTR2UV(args ? va_arg(*args, void*) : argsv);
            base = 16;
@@ -8251,12 +8260,50 @@ 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 && !vectorize) ?
+#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;
+           vectorize = FALSE;
            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");
@@ -8278,8 +8325,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. */
@@ -8310,8 +8358,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;
@@ -8319,9 +8373,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* SPECIAL */
 
        case 'n':
-           vectorize = FALSE;
            i = SvCUR(sv) - origlen;
-           if (args) {
+           if (args && !vectorize) {
                switch (intsize) {
                case 'h':       *(va_arg(*args, short*)) = i; break;
                default:        *(va_arg(*args, int*)) = i; break;
@@ -8334,6 +8387,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            }
            else
                sv_setuv_mg(argsv, (UV)i);
+           vectorize = FALSE;
            continue;   /* not "break" */
 
            /* UNKNOWN */
@@ -8767,7 +8821,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;
        }
     }
@@ -8869,10 +8922,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 */
@@ -8882,7 +8935,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);
         }
     }
@@ -9063,9 +9116,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));
@@ -9300,7 +9354,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;
@@ -9768,6 +9822,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;
@@ -10105,16 +10160,29 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     Copy(proto_perl->Inexttype, PL_nexttype, 5,        I32);
     PL_nexttoke                = proto_perl->Inexttoke;
 
-    PL_linestr         = sv_dup_inc(proto_perl->Ilinestr, param);
-    i = proto_perl->Ibufptr - SvPVX(proto_perl->Ilinestr);
-    PL_bufptr          = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ioldbufptr - SvPVX(proto_perl->Ilinestr);
-    PL_oldbufptr       = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ioldoldbufptr - SvPVX(proto_perl->Ilinestr);
-    PL_oldoldbufptr    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+    /* XXX This is probably masking the deeper issue of why
+     * SvANY(proto_perl->Ilinestr) can be NULL at this point. For test case:
+     * http://archive.develooper.com/perl5-porters%40perl.org/msg83298.html
+     * (A little debugging with a watchpoint on it may help.)
+     */
+    if (SvANY(proto_perl->Ilinestr)) {
+       PL_linestr              = sv_dup_inc(proto_perl->Ilinestr, param);
+       i = proto_perl->Ibufptr - SvPVX(proto_perl->Ilinestr);
+       PL_bufptr               = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+       i = proto_perl->Ioldbufptr - SvPVX(proto_perl->Ilinestr);
+       PL_oldbufptr    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+       i = proto_perl->Ioldoldbufptr - SvPVX(proto_perl->Ilinestr);
+       PL_oldoldbufptr = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+       i = proto_perl->Ilinestart - SvPVX(proto_perl->Ilinestr);
+       PL_linestart    = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+    }
+    else {
+        PL_linestr = NEWSV(65,79);
+        sv_upgrade(PL_linestr,SVt_PVIV);
+        sv_setpvn(PL_linestr,"",0);
+       PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr);
+    }
     PL_bufend          = SvPVX(PL_linestr) + SvCUR(PL_linestr);
-    i = proto_perl->Ilinestart - SvPVX(proto_perl->Ilinestr);
-    PL_linestart       = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
     PL_pending_ident   = proto_perl->Ipending_ident;
     PL_sublex_info     = proto_perl->Isublex_info;     /* XXX not quite right */
 
@@ -10135,11 +10203,19 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_padix_floor             = proto_perl->Ipadix_floor;
     PL_pad_reset_pending       = proto_perl->Ipad_reset_pending;
 
-    i = proto_perl->Ilast_uni - SvPVX(proto_perl->Ilinestr);
-    PL_last_uni                = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    i = proto_perl->Ilast_lop - SvPVX(proto_perl->Ilinestr);
-    PL_last_lop                = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
-    PL_last_lop_op     = proto_perl->Ilast_lop_op;
+    /* XXX See comment on SvANY(proto_perl->Ilinestr) above */
+    if (SvANY(proto_perl->Ilinestr)) {
+       i = proto_perl->Ilast_uni - SvPVX(proto_perl->Ilinestr);
+       PL_last_uni             = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+       i = proto_perl->Ilast_lop - SvPVX(proto_perl->Ilinestr);
+       PL_last_lop             = SvPVX(PL_linestr) + (i < 0 ? 0 : i);
+       PL_last_lop_op  = proto_perl->Ilast_lop_op;
+    }
+    else {
+       PL_last_uni     = SvPVX(PL_linestr);
+       PL_last_lop     = SvPVX(PL_linestr);
+       PL_last_lop_op  = 0;
+    }
     PL_in_my           = proto_perl->Iin_my;
     PL_in_my_stash     = hv_dup(proto_perl->Iin_my_stash, param);
 #ifdef FCRYPT
@@ -10469,7 +10545,7 @@ The PV of the sv is returned.
 char *
 Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
 {
-     if (SvPOK(sv) && !DO_UTF8(sv) && SvROK(encoding)) {
+    if (SvPOK(sv) && !DO_UTF8(sv) && SvROK(encoding)) {
          SV *uni;
          STRLEN len;
          char *s;
@@ -10480,7 +10556,16 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
          EXTEND(SP, 3);
          XPUSHs(encoding);
          XPUSHs(sv);
+/* 
+  NI-S 2002/07/09
+  Passing sv_yes is wrong - it needs to be or'ed set of constants
+  for Encode::XS, while UTf-8 decode (currently) assumes a true value means 
+  remove converted chars from source.
+
+  Both will default the value - let them.
+  
          XPUSHs(&PL_sv_yes);
+*/
          PUTBACK;
          call_method("decode", G_SCALAR);
          SPAGAIN;
@@ -10496,8 +10581,9 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding)
          FREETMPS;
          LEAVE;
          SvUTF8_on(sv);
-     }
-     return SvPVX(sv);
+    }
+    return SvPVX(sv);
 }
 
 
+