summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doop.c28
-rw-r--r--op.c9
2 files changed, 27 insertions, 10 deletions
diff --git a/doop.c b/doop.c
index e4a516a1a3..b3c4acbb13 100644
--- a/doop.c
+++ b/doop.c
@@ -402,6 +402,7 @@ S_do_trans_count_utf8(pTHX_ SV *sv)/* SPC - OK */
HV* hv = (HV*)SvRV(rv);
SV** svp = hv_fetch(hv, "NONE", 4, FALSE);
UV none = svp ? SvUV(*svp) : 0x7fffffff;
+ UV extra = none + 1;
UV uv;
U8 hibit = 0;
@@ -417,7 +418,7 @@ S_do_trans_count_utf8(pTHX_ SV *sv)/* SPC - OK */
send = s + len;
while (s < send) {
- if ((uv = swash_fetch(rv, s)) < none)
+ if ((uv = swash_fetch(rv, s)) < none || uv == extra)
matches++;
s += UTF8SKIP(s);
}
@@ -443,6 +444,7 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
UV none = svp ? SvUV(*svp) : 0x7fffffff;
UV extra = none + 1;
UV final;
+ bool havefinal = FALSE;
UV uv;
STRLEN len;
U8 *dstart, *dend;
@@ -463,8 +465,10 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
start = s;
svp = hv_fetch(hv, "FINAL", 5, FALSE);
- if (svp)
+ if (svp) {
final = SvUV(*svp);
+ havefinal = TRUE;
+ }
if (grows) {
/* d needs to be bigger than s, in case e.g. upgrading is required */
@@ -510,10 +514,22 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
}
else if (uv == extra && !del) {
matches++;
- s += UTF8SKIP(s);
- if (uv != puv) {
- d = uvchr_to_utf8(d, final);
- puv = final;
+ if (havefinal) {
+ s += UTF8SKIP(s);
+ if (puv != final) {
+ d = uvchr_to_utf8(d, final);
+ puv = final;
+ }
+ }
+ else {
+ STRLEN len;
+ uv = utf8_to_uvchr(s, &len);
+ if (uv != puv) {
+ Copy(s, d, len, U8);
+ d += len;
+ puv = uv;
+ }
+ s += len;
}
continue;
}
diff --git a/op.c b/op.c
index 25e7aa5058..5cdb3df2f7 100644
--- a/op.c
+++ b/op.c
@@ -2710,7 +2710,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
I32 from_utf = o->op_private & OPpTRANS_FROM_UTF;
I32 to_utf = o->op_private & OPpTRANS_TO_UTF;
U8* tsave = from_utf ? NULL : trlist_upgrade(&t, &tend);
- U8* rsave = to_utf ? NULL : trlist_upgrade(&r, &rend);
+ U8* rsave = (to_utf || !rlen) ? NULL : trlist_upgrade(&r, &rend);
if (complement) {
U8 tmpbuf[UTF8_MAXLEN+1];
@@ -2832,9 +2832,10 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
if (rfirst + diff > max)
max = rfirst + diff;
- rfirst += diff + 1;
if (!grows)
- grows = (UNISKIP(tfirst) < UNISKIP(rfirst));
+ grows = (tfirst < rfirst &&
+ UNISKIP(tfirst) < UNISKIP(rfirst + diff));
+ rfirst += diff + 1;
}
tfirst += diff + 1;
}
@@ -2856,7 +2857,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
if (transv)
SvREFCNT_dec(transv);
- if (!del && havefinal)
+ if (!del && havefinal && rlen)
(void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
newSVuv((UV)final), 0);