This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use HEKf
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index 24477ba..3360bf4 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1719,7 +1719,7 @@ S_not_a_number(pTHX_ SV *const sv)
 
      if (DO_UTF8(sv)) {
           dsv = newSVpvs_flags("", SVs_TEMP);
-          pv = sv_uni_display(dsv, sv, 10, 0);
+          pv = sv_uni_display(dsv, sv, 10, UNI_DISPLAY_ISPRINT);
      } else {
          char *d = tmpbuf;
          const char * const limit = tmpbuf + sizeof(tmpbuf) - 8;
@@ -2961,6 +2961,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
                if (lp) {
                    *lp = SvCUR(buffer);
                }
+                if ( SvUTF8(buffer) ) SvUTF8_on(sv);
                return SvPVX(buffer);
            }
            else {
@@ -3665,7 +3666,8 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
        GvSTASH(dstr) = GvSTASH(sstr);
        if (GvSTASH(dstr))
            Perl_sv_add_backref(aTHX_ MUTABLE_SV(GvSTASH(dstr)), dstr);
-       gv_name_set(MUTABLE_GV(dstr), name, len, GV_ADD);
+        gv_name_set(MUTABLE_GV(dstr), name, len,
+                        GV_ADD | (GvNAMEUTF8(sstr) ? SVf_UTF8 : 0 ));
        SvFAKE_on(dstr);        /* can coerce to non-glob */
     }
 
@@ -3844,16 +3846,21 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
                            Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                                        (const char *)
                                        (CvCONST(cv)
-                                        ? "Constant subroutine %s::%s redefined"
-                                        : "Subroutine %s::%s redefined"),
-                                       HvNAME_get(GvSTASH((const GV *)dstr)),
-                                       GvENAME(MUTABLE_GV(dstr)));
+                                        ? "Constant subroutine %"HEKf
+                                          "::%"HEKf" redefined"
+                                        : "Subroutine %"HEKf"::%"HEKf
+                                          " redefined"),
+                               HEKfARG(
+                                HvNAME_HEK(GvSTASH((const GV *)dstr))
+                               ),
+                               HEKfARG(GvENAME_HEK(MUTABLE_GV(dstr))));
                        }
                    }
                if (!intro)
-                   cv_ckproto_len(cv, (const GV *)dstr,
+                   cv_ckproto_len_flags(cv, (const GV *)dstr,
                                   SvPOK(sref) ? SvPVX_const(sref) : NULL,
-                                  SvPOK(sref) ? SvCUR(sref) : 0);
+                                  SvPOK(sref) ? SvCUR(sref)  : 0,
+                                   SvPOK(sref) ? SvUTF8(sref) : 0);
            }
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
@@ -4578,6 +4585,49 @@ Perl_sv_setpv_mg(pTHX_ register SV *const sv, register const char *const ptr)
     SvSETMAGIC(sv);
 }
 
+void
+Perl_sv_sethek(pTHX_ register SV *const sv, const HEK *const hek)
+{
+    dVAR;
+
+    PERL_ARGS_ASSERT_SV_SETHEK;
+
+    if (!hek) {
+       return;
+    }
+
+    if (HEK_LEN(hek) == HEf_SVKEY) {
+       sv_setsv(sv, *(SV**)HEK_KEY(hek));
+        return;
+    } else {
+       const int flags = HEK_FLAGS(hek);
+       if (flags & HVhek_WASUTF8) {
+           STRLEN utf8_len = HEK_LEN(hek);
+           char *as_utf8 = (char *)bytes_to_utf8((U8*)HEK_KEY(hek), &utf8_len);
+           sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
+           SvUTF8_on(sv);
+            return;
+       } else if (flags & (HVhek_REHASH|HVhek_UNSHARED)) {
+           sv_setpvn(sv, HEK_KEY(hek), HEK_LEN(hek));
+           if (HEK_UTF8(hek))
+               SvUTF8_on(sv);
+            return;
+       }
+        {
+           sv_upgrade(sv, SVt_PV);
+           sv_usepvn_flags(sv, (char *)HEK_KEY(share_hek_hek(hek)), HEK_LEN(hek), SV_HAS_TRAILING_NUL);
+           SvLEN_set(sv, 0);
+           SvREADONLY_on(sv);
+           SvFAKE_on(sv);
+           SvPOK_on(sv);
+           if (HEK_UTF8(hek))
+               SvUTF8_on(sv);
+            return;
+       }
+    }
+}
+
+
 /*
 =for apidoc sv_usepvn_flags
 
@@ -4944,12 +4994,43 @@ Perl_sv_catpvn_flags(pTHX_ register SV *const dsv, register const char *sstr, re
     const char * const dstr = SvPV_force_flags(dsv, dlen, flags);
 
     PERL_ARGS_ASSERT_SV_CATPVN_FLAGS;
+    assert((flags & (SV_CATBYTES|SV_CATUTF8)) != (SV_CATBYTES|SV_CATUTF8));
 
-    SvGROW(dsv, dlen + slen + 1);
-    if (sstr == dstr)
+    if (!(flags & SV_CATBYTES) || !SvUTF8(dsv)) {
+      if (flags & SV_CATUTF8 && !SvUTF8(dsv)) {
+        sv_utf8_upgrade_flags_grow(dsv, 0, slen);
+        dlen = SvCUR(dsv);
+      }
+      else SvGROW(dsv, dlen + slen + 1);
+      if (sstr == dstr)
        sstr = SvPVX_const(dsv);
-    Move(sstr, SvPVX(dsv) + dlen, slen, char);
-    SvCUR_set(dsv, SvCUR(dsv) + slen);
+      Move(sstr, SvPVX(dsv) + dlen, slen, char);
+      SvCUR_set(dsv, SvCUR(dsv) + slen);
+    }
+    else {
+       /* We inline bytes_to_utf8, to avoid an extra malloc. */
+       const char * const send = sstr + slen;
+       U8 *d;
+
+       /* Something this code does not account for, which I think is
+          impossible; it would require the same pv to be treated as
+          bytes *and* utf8, which would indicate a bug elsewhere. */
+       assert(sstr != dstr);
+
+       SvGROW(dsv, dlen + slen * 2);
+       d = (U8 *)SvPVX(dsv) + dlen;
+
+       while (sstr < send) {
+           const UV uv = NATIVE_TO_ASCII((U8)*sstr++);
+           if (UNI_IS_INVARIANT(uv))
+               *d++ = (U8)UTF_TO_NATIVE(uv);
+           else {
+               *d++ = (U8)UTF8_EIGHT_BIT_HI(uv);
+               *d++ = (U8)UTF8_EIGHT_BIT_LO(uv);
+           }
+       }
+       SvCUR_set(dsv, d-(const U8 *)SvPVX(dsv));
+    }
     *SvEND(dsv) = '\0';
     (void)SvPOK_only_UTF8(dsv);                /* validate pointer */
     SvTAINT(dsv);
@@ -5848,7 +5929,6 @@ Perl_sv_replace(pTHX_ register SV *const sv, register SV *const nsv)
 STATIC void
 S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
 {
-    char *stash;
     SV *gvname;
     GV *anongv;
 
@@ -5868,10 +5948,10 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv)
     }
 
     /* if not, anonymise: */
-    stash  = GvSTASH(gv) && HvNAME(GvSTASH(gv))
-              ? HvENAME(GvSTASH(gv)) : NULL;
-    gvname = Perl_newSVpvf(aTHX_ "%s::__ANON__",
-                                       stash ? stash : "__ANON__");
+    gvname = (GvSTASH(gv) && HvNAME(GvSTASH(gv)) && HvENAME(GvSTASH(gv)))
+                    ? newSVhek(HvENAME_HEK(GvSTASH(gv)))
+                    : newSVpvn_flags( "__ANON__", 8, 0 );
+    sv_catpvs(gvname, "::__ANON__");
     anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
     SvREFCNT_dec(gvname);
 
@@ -5999,7 +6079,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
                {
                    if (PL_stashcache)
                        (void)hv_delete(PL_stashcache, name,
-                           HvNAMELEN_get((HV*)sv), G_DISCARD);
+                           HvNAMEUTF8((HV*)sv) ? -HvNAMELEN_get((HV*)sv) : HvNAMELEN_get((HV*)sv), G_DISCARD);
                    hv_name_set((HV*)sv, NULL, 0, 0);
                }
 
@@ -6276,8 +6356,8 @@ S_curse(pTHX_ SV * const sv, const bool check_refcnt) {
        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 created new reference to dead object '%"HEKf"'",
+                  HEKfARG(HvNAME_HEK(stash)));
            /* DESTROY gave object new lease on life */
            return FALSE;
        }
@@ -8355,7 +8435,7 @@ Perl_newSVhek(pTHX_ const HEK *const hek)
               into an hv routine with a regular hash.
               Similarly, a hash that isn't using shared hash keys has to have
               the flag in every key so that we know not to try to call
-              share_hek_kek on it.  */
+              share_hek_hek on it.  */
 
            SV * const sv = newSVpvn (HEK_KEY(hek), HEK_LEN(hek));
            if (HEK_UTF8(hek))
@@ -8783,7 +8863,8 @@ Perl_sv_2io(pTHX_ SV *const sv)
            gv = MUTABLE_GV(sv);
            io = GvIO(gv);
            if (!io)
-               Perl_croak(aTHX_ "Bad filehandle: %s", GvNAME(gv));
+               Perl_croak(aTHX_ "Bad filehandle: %"HEKf,
+                                    HEKfARG(GvNAME_HEK(gv)));
            break;
        }
        /* FALL THROUGH */
@@ -9054,12 +9135,8 @@ const char *
 Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 {
     PERL_ARGS_ASSERT_SV_REFTYPE;
-
-    /* The fact that I don't need to downcast to char * everywhere, only in ?:
-       inside return suggests a const propagation bug in g++.  */
     if (ob && SvOBJECT(sv)) {
-       char * const name = HvNAME_get(SvSTASH(sv));
-       return name ? name : (char *) "__ANON__";
+       return SvPV_nolen_const(sv_ref(NULL, sv, ob));
     }
     else {
        switch (SvTYPE(sv)) {
@@ -9097,6 +9174,34 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob)
 }
 
 /*
+=for apidoc sv_ref
+
+Returns a SV describing what the SV passed in is a reference to.
+
+=cut
+*/
+
+SV *
+Perl_sv_ref(pTHX_ register SV *dst, const SV *const sv, const int ob)
+{
+    PERL_ARGS_ASSERT_SV_REF;
+
+    if (!dst)
+        dst = sv_newmortal();
+
+    if (ob && SvOBJECT(sv)) {
+       HvNAME_get(SvSTASH(sv))
+                    ? sv_sethek(dst, HvNAME_HEK(SvSTASH(sv)))
+                    : sv_setpvn(dst, "__ANON__", 8);
+    }
+    else {
+        const char * reftype = sv_reftype(sv, 0);
+        sv_setpv(dst, reftype);
+    }
+    return dst;
+}
+
+/*
 =for apidoc sv_isobject
 
 Returns a boolean indicating whether the SV is an RV pointing to a blessed
@@ -10073,9 +10178,12 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                %p              include pointer address (standard)      
                %-p     (SVf)   include an SV (previously %_)
                %-<num>p        include an SV with precision <num>      
-               %<num>p         reserved for future extensions
+               %2p             include a HEK
+               %3p             include a HEK with precision of 256
+               %<num>p         (where num != 2 or 3) reserved for future
+                               extensions
 
-       Robin Barker 2005-07-14
+       Robin Barker 2005-07-14 (but modified since)
 
                %1p     (VDf)   removed.  RMB 2007-10-19
 */
@@ -10097,6 +10205,14 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
                        is_utf8 = TRUE;
                    goto string;
                }
+               else if (n==2 || n==3) {        /* HEKf */
+                   HEK * const hek = va_arg(*args, HEK *);
+                   eptr = HEK_KEY(hek);
+                   elen = HEK_LEN(hek);
+                   if (HEK_UTF8(hek)) is_utf8 = TRUE;
+                   if (n==3) precis = 256, has_precis = TRUE;
+                   goto string;
+               }
                else if (n) {
                    Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL),
                                     "internal %%<num>p might conflict with future printf extensions");
@@ -11690,7 +11806,8 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
            const HEK * const hvname = HvNAME_HEK(sstr);
            if (hvname) {
                /** don't clone stashes if they already exist **/
-               dstr = MUTABLE_SV(gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname), 0));
+               dstr = MUTABLE_SV(gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname),
+                                                HEK_UTF8(hvname) ? SVf_UTF8 : 0));
                ptr_table_store(PL_ptr_table, sstr, dstr);
                return dstr;
            }
@@ -13724,7 +13841,7 @@ S_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ,
            return NULL;
        av = MUTABLE_AV((*av_fetch(CvPADLIST(cv), 0, FALSE)));
        sv = *av_fetch(av, targ, FALSE);
-       sv_setpvn(name, SvPV_nolen_const(sv), SvCUR(sv));
+       sv_setsv(name, sv);
     }
 
     if (subscript_type == FUV_SUBSCRIPT_HASH) {
@@ -14216,8 +14333,9 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv)
            if (varname)
                sv_insert(varname, 0, 0, " ", 1);
        }
-       Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit,
-               varname ? SvPV_nolen_const(varname) : "",
+       /* diag_listed_as: Use of uninitialized value%s */
+       Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit_sv,
+               SVfARG(varname ? varname : &PL_sv_no),
                " in ", OP_DESC(PL_op));
     }
     else