+ if (left_utf || right_utf) {
+ UV duc, luc, ruc;
+ char *dcorig = dc;
+ char *dcsave = NULL;
+ STRLEN lulen = leftlen;
+ STRLEN rulen = rightlen;
+ STRLEN ulen;
+
+ switch (optype) {
+ case OP_BIT_AND:
+ while (lulen && rulen) {
+ luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
+ lc += ulen;
+ lulen -= ulen;
+ ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
+ rc += ulen;
+ rulen -= ulen;
+ duc = luc & ruc;
+ dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+ }
+ if (sv == left || sv == right)
+ (void)sv_usepvn(sv, dcorig, needlen);
+ SvCUR_set(sv, dc - dcorig);
+ break;
+ case OP_BIT_XOR:
+ while (lulen && rulen) {
+ luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
+ lc += ulen;
+ lulen -= ulen;
+ ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
+ rc += ulen;
+ rulen -= ulen;
+ duc = luc ^ ruc;
+ dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+ }
+ goto mop_up_utf;
+ case OP_BIT_OR:
+ while (lulen && rulen) {
+ luc = utf8n_to_uvchr((U8*)lc, lulen, &ulen, UTF8_ALLOW_ANYUV);
+ lc += ulen;
+ lulen -= ulen;
+ ruc = utf8n_to_uvchr((U8*)rc, rulen, &ulen, UTF8_ALLOW_ANYUV);
+ rc += ulen;
+ rulen -= ulen;
+ duc = luc | ruc;
+ dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+ }
+ mop_up_utf:
+ if (rulen)
+ dcsave = savepvn(rc, rulen);
+ else if (lulen)
+ dcsave = savepvn(lc, lulen);
+ if (sv == left || sv == right)
+ (void)sv_usepvn(sv, dcorig, needlen); /* Uses Renew(). */
+ SvCUR_set(sv, dc - dcorig);
+ if (rulen)
+ sv_catpvn(sv, dcsave, rulen);
+ else if (lulen)
+ sv_catpvn(sv, dcsave, lulen);
+ else
+ *SvEND(sv) = '\0';
+ Safefree(dcsave);
+ break;
+ default:
+ if (sv == left || sv == right)
+ Safefree(dcorig);
+ Perl_croak(aTHX_ "panic: do_vop called for op %u (%s)",
+ (unsigned)optype, PL_op_name[optype]);
+ }
+ SvUTF8_on(sv);
+ goto finish;
+ }
+ else