X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=doop.c;h=074be99e1887e8ba33d6c49612ae712265a4ff03;hb=af960fef4eb57cfacbc13759993e50a8f1de8367;hp=5e3318a4a750ce06a977661f45459a98e3954cab;hpb=01ec43d06089361423d61a40521883bf73e1944a;p=p5sagit%2Fp5-mst-13.2.git diff --git a/doop.c b/doop.c index 5e3318a..074be99 100644 --- a/doop.c +++ b/doop.c @@ -21,16 +21,18 @@ #endif #endif -#define HALF_UPGRADE(start,end) \ +#define HALF_UTF8_UPGRADE(start,end) \ STMT_START { \ + if ((start)<(end)) { \ U8* NeWsTr; \ - STRLEN LeN = LeN = (end) - (start); \ + STRLEN LeN = (end) - (start); \ NeWsTr = bytes_to_utf8(start, &LeN); \ - Copy(NeWsTr,start,LeN,U8*); \ - end = (start) + len; \ + Safefree(start); \ + (start) = NeWsTr; \ + (end) = (start) + LeN; \ + } \ } STMT_END - STATIC I32 S_do_trans_simple(pTHX_ SV *sv) { @@ -91,8 +93,8 @@ S_do_trans_simple(pTHX_ SV *sv) } *d = '\0'; sv_setpvn(sv, (const char*)dstart, d - dstart); + Safefree(dstart); SvUTF8_on(sv); - SvLEN_set(sv, 2*len+1); SvSETMAGIC(sv); return matches; } @@ -240,16 +242,16 @@ S_do_trans_simple_utf8(pTHX_ SV *sv)/* SPC - OK */ s += UTF8SKIP(s); matches++; if ((uv & 0x80) && !isutf++) - HALF_UPGRADE(dstart,d); + HALF_UTF8_UPGRADE(dstart,d); d = uv_to_utf8(d, uv); } else if (uv == none) { int i; i = UTF8SKIP(s); if (i > 1 && !isutf++) - HALF_UPGRADE(dstart,d); + HALF_UTF8_UPGRADE(dstart,d); while(i--) - *d++ = *s++; + *d++ = *s++; } else if (uv == extra) { int i; @@ -257,7 +259,7 @@ S_do_trans_simple_utf8(pTHX_ SV *sv)/* SPC - OK */ s += i; matches++; if (i > 1 && !isutf++) - HALF_UPGRADE(dstart,d); + HALF_UTF8_UPGRADE(dstart,d); d = uv_to_utf8(d, final); } else @@ -353,11 +355,11 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */ matches++; if (uv != puv) { if ((uv & 0x80) && !isutf++) - HALF_UPGRADE(dst,d); + HALF_UTF8_UPGRADE(dst,d); d = uv_to_utf8(d, uv); puv = uv; } - s += UTF8SKIP(s); + s += UTF8SKIP(s); continue; } else if (uv == none) { /* "none" is unmapped character */ @@ -485,7 +487,7 @@ Perl_do_join(pTHX_ register SV *sv, SV *del, register SV **mark, register SV **s (void)SvUPGRADE(sv, SVt_PV); if (SvLEN(sv) < len + items) { /* current length is way too short */ while (items-- > 0) { - if (*mark && !SvGMAGICAL(*mark) && SvOK(*mark)) { + if (*mark && !SvGAMAGIC(*mark) && SvOK(*mark)) { SvPV(*mark, tmplen); len += tmplen; } @@ -903,6 +905,7 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) char *rsave; bool left_utf = DO_UTF8(left); bool right_utf = DO_UTF8(right); + I32 needlen; if (left_utf && !right_utf) sv_utf8_upgrade(right); @@ -915,17 +918,23 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) rsave = rc = SvPV(right, rightlen); len = leftlen < rightlen ? leftlen : rightlen; lensave = len; - if (SvOK(sv) || SvTYPE(sv) > SVt_PVMG) { + if ((left_utf || right_utf) && (sv == left || sv == right)) { + needlen = optype == OP_BIT_AND ? len : leftlen + rightlen; + Newz(801, dc, needlen + 1, char); + } + else if (SvOK(sv) || SvTYPE(sv) > SVt_PVMG) { STRLEN n_a; dc = SvPV_force(sv, n_a); if (SvCUR(sv) < len) { dc = SvGROW(sv, len + 1); (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1); } + if (optype != OP_BIT_AND && (left_utf || right_utf)) + dc = SvGROW(sv, leftlen + rightlen + 1); } else { - I32 needlen = ((optype == OP_BIT_AND) - ? len : (leftlen > rightlen ? leftlen : rightlen)); + needlen = ((optype == OP_BIT_AND) + ? len : (leftlen > rightlen ? leftlen : rightlen)); Newz(801, dc, needlen + 1, char); (void)sv_usepvn(sv, dc, needlen); dc = SvPVX(sv); /* sv_usepvn() calls Renew() */ @@ -934,14 +943,11 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) (void)SvPOK_only(sv); if (left_utf || right_utf) { UV duc, luc, ruc; + char *dcsave = dc; STRLEN lulen = leftlen; STRLEN rulen = rightlen; - STRLEN dulen = 0; I32 ulen; - if (optype != OP_BIT_AND) - dc = SvGROW(sv, leftlen+rightlen+1); - switch (optype) { case OP_BIT_AND: while (lulen && rulen) { @@ -954,8 +960,9 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) duc = luc & ruc; dc = (char*)uv_to_utf8((U8*)dc, duc); } - dulen = dc - SvPVX(sv); - SvCUR_set(sv, dulen); + if (sv == left || sv == right) + (void)sv_usepvn(sv, dcsave, needlen); + SvCUR_set(sv, dc - dcsave); break; case OP_BIT_XOR: while (lulen && rulen) { @@ -981,8 +988,9 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right) dc = (char*)uv_to_utf8((U8*)dc, duc); } mop_up_utf: - dulen = dc - SvPVX(sv); - SvCUR_set(sv, dulen); + if (sv == left || sv == right) + (void)sv_usepvn(sv, dcsave, needlen); + SvCUR_set(sv, dc - dcsave); if (rulen) sv_catpvn(sv, rc, rulen); else if (lulen)