diff options
-rw-r--r-- | doop.c | 28 | ||||
-rw-r--r-- | op.c | 9 |
2 files changed, 27 insertions, 10 deletions
@@ -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; } @@ -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); |