- needlen = optype == OP_BIT_AND
- ? len : (leftlen > rightlen ? leftlen : rightlen);
- Newxz(dc, needlen + 1, char);
- sv_usepvn_flags(sv, dc, needlen, SV_HAS_TRAILING_NUL);
- dc = SvPVX(sv); /* sv_usepvn() calls Renew() */
- }
- 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(); defaults to nomg */
- SvCUR_set(sv, dc - dcorig);
- if (rulen)
- sv_catpvn_nomg(sv, dcsave, rulen);
- else if (lulen)
- sv_catpvn_nomg(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;