Use -Dusedevel; regen Configure and the respective Porting stuff.
[p5sagit/p5-mst-13.2.git] / doop.c
diff --git a/doop.c b/doop.c
index 5e3318a..074be99 100644 (file)
--- a/doop.c
+++ b/doop.c
 #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)