}
}
+PP(pp_dor)
+{
+ /* Most of this is lifted straight from pp_defined */
+ dSP;
+ register SV* sv;
+
+ sv = TOPs;
+ if (!sv || !SvANY(sv)) {
+ --SP;
+ RETURNOP(cLOGOP->op_other);
+ }
+
+ switch (SvTYPE(sv)) {
+ case SVt_PVAV:
+ if (AvMAX(sv) >= 0 || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+ RETURN;
+ break;
+ case SVt_PVHV:
+ if (HvARRAY(sv) || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+ RETURN;
+ break;
+ case SVt_PVCV:
+ if (CvROOT(sv) || CvXSUB(sv))
+ RETURN;
+ break;
+ default:
+ if (SvGMAGICAL(sv))
+ mg_get(sv);
+ if (SvOK(sv))
+ RETURN;
+ }
+
+ --SP;
+ RETURNOP(cLOGOP->op_other);
+}
+
PP(pp_add)
{
dSP; dATARGET; bool useleft; tryAMAGICbin(add,opASSIGN);
I32 preeminent = 0;
if (SvTYPE(hv) == SVt_PVHV) {
- if (PL_op->op_private & OPpLVAL_INTRO)
- preeminent = SvRMAGICAL(hv) ? 1 : hv_exists_ent(hv, keysv, 0);
+ if (PL_op->op_private & OPpLVAL_INTRO) {
+ MAGIC *mg;
+ HV *stash;
+ /* does the element we're localizing already exist? */
+ preeminent =
+ /* can we determine whether it exists? */
+ ( !SvRMAGICAL(hv)
+ || mg_find((SV*)hv, PERL_MAGIC_env)
+ || ( (mg = mg_find((SV*)hv, PERL_MAGIC_tied))
+ /* Try to preserve the existenceness of a tied hash
+ * element by using EXISTS and DELETE if possible.
+ * Fallback to FETCH and STORE otherwise */
+ && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg))))
+ && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
+ && gv_fetchmethod_autoload(stash, "DELETE", TRUE)
+ )
+ ) ? hv_exists_ent(hv, keysv, 0) : 1;
+
+ }
he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
svp = he ? &HeVAL(he) : 0;
}
STRLEN keylen;
char *key = SvPV(keysv, keylen);
SAVEDELETE(hv, savepvn(key,keylen), keylen);
- } else {
- SV *sv;
+ } else
save_helem(hv, keysv, svp);
- sv = *svp;
- /* If we're localizing a tied hash element, this new
- * sv won't actually be stored in the hash - so it
- * won't get reaped when the localize ends. Ensure it
- * gets reaped by mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
- sv_2mortal(sv);
- }
}
}
else if (PL_op->op_private & OPpDEREF)
/* known replacement string? */
if (dstr) {
- c = SvPV(dstr, clen);
- doutf8 = DO_UTF8(dstr);
+ /* replacement needing upgrading? */
+ if (DO_UTF8(TARG) && !doutf8) {
+ SV *nsv = sv_newmortal();
+ SvSetSV(nsv, dstr);
+ if (PL_encoding)
+ sv_recode_to_utf8(nsv, PL_encoding);
+ else
+ sv_utf8_upgrade(nsv);
+ c = SvPV(nsv, clen);
+ doutf8 = TRUE;
+ }
+ else {
+ c = SvPV(dstr, clen);
+ doutf8 = DO_UTF8(dstr);
+ }
}
else {
c = Nullch;
SPAGAIN;
}
SvTAINT(TARG);
+ if (doutf8)
+ SvUTF8_on(TARG);
LEAVE_SCOPE(oldsave);
RETURN;
}
PUSHs(lv);
RETURN;
}
- if (PL_op->op_private & OPpLVAL_INTRO) {
- SV *sv;
+ if (PL_op->op_private & OPpLVAL_INTRO)
save_aelem(av, elem, svp);
- sv = *svp;
- /* If we're localizing a tied array element, this new sv
- * won't actually be stored in the array - so it won't get
- * reaped when the localize ends. Ensure it gets reaped by
- * mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
- sv_2mortal(sv);
- }
else if (PL_op->op_private & OPpDEREF)
vivify_ref(*svp, PL_op->op_private & OPpDEREF);
}