Sync file with libnet-1.0901-tobe
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index 63facbe..e4354ea 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -550,8 +550,11 @@ PP(pp_gelem)
            tmpRef = (SV*)GvCVu(gv);
        break;
     case 'F':
-       if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */
+       if (strEQ(elem, "FILEHANDLE")) {
+           /* finally deprecated in 5.8.0 */
+           deprecate("*glob{FILEHANDLE}");
            tmpRef = (SV*)GvIOp(gv);
+       }
        else
        if (strEQ(elem, "FORMAT"))
            tmpRef = (SV*)GvFORM(gv);
@@ -1071,9 +1074,13 @@ PP(pp_divide)
 #else
                 /* Otherwise we only attempt it if either or both operands
                    would not be preserved by an NV.  If both fit in NVs
-                   we fall through to the NV divide code below.  */
-                && ((left > ((UV)1 << NV_PRESERVES_UV_BITS))
-                    || (right > ((UV)1 << NV_PRESERVES_UV_BITS)))
+                   we fall through to the NV divide code below.  However,
+                   as left >= right to ensure integer result here, we know that
+                   we can skip the test on the right operand - right big
+                   enough not to be preserved can't get here unless left is
+                   also too big.  */
+
+                && (left > ((UV)1 << NV_PRESERVES_UV_BITS))
 #endif
                 ) {
                 /* Integer division can't overflow, but it can be imprecise.  */
@@ -1249,10 +1256,33 @@ PP(pp_repeat)
        MEXTEND(MARK, max);
        if (count > 1) {
            while (SP > MARK) {
+#if 0
+             /* This code was intended to fix 20010809.028:
+
+                $x = 'abcd';
+                for (($x =~ /./g) x 2) {
+                    print chop; # "abcdabcd" expected as output.
+                }
+
+              * but that change (#11635) broke this code:
+
+              $x = [("foo")x2]; # only one "foo" ended up in the anonlist.
+
+              * I can't think of a better fix that doesn't introduce
+              * an efficiency hit by copying the SVs. The stack isn't
+              * refcounted, and mortalisation obviously doesn't
+              * Do The Right Thing when the stack has more than
+              * one pointer to the same mortal value.
+              * .robin.
+              */
                if (*SP) {
                    *SP = sv_2mortal(newSVsv(*SP));
                    SvREADONLY_on(*SP);
                }
+#else
+               if (*SP)
+                  SvTEMP_off((*SP));
+#endif
                SP--;
            }
            MARK++;
@@ -1491,11 +1521,6 @@ PP(pp_lt)
                    RETURN;
                }
                auv = SvUVX(TOPs);
-               if (auv >= (UV) IV_MAX) {
-                   /* As (b) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_no);
-                   RETURN;
-               }
                SETs(boolSV(auv < (UV)biv));
                RETURN;
            }
@@ -1512,11 +1537,6 @@ PP(pp_lt)
                }
                buv = SvUVX(TOPs);
                SP--;
-               if (buv > (UV) IV_MAX) {
-                   /* As (a) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_yes);
-                   RETURN;
-               }
                SETs(boolSV((UV)aiv < buv));
                RETURN;
            }
@@ -1569,11 +1589,6 @@ PP(pp_gt)
                    RETURN;
                }
                auv = SvUVX(TOPs);
-               if (auv > (UV) IV_MAX) {
-                   /* As (b) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_yes);
-                   RETURN;
-               }
                SETs(boolSV(auv > (UV)biv));
                RETURN;
            }
@@ -1590,11 +1605,6 @@ PP(pp_gt)
                }
                buv = SvUVX(TOPs);
                SP--;
-               if (buv >= (UV) IV_MAX) {
-                   /* As (a) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_no);
-                   RETURN;
-               }
                SETs(boolSV((UV)aiv > buv));
                RETURN;
            }
@@ -1647,11 +1657,6 @@ PP(pp_le)
                    RETURN;
                }
                auv = SvUVX(TOPs);
-               if (auv > (UV) IV_MAX) {
-                   /* As (b) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_no);
-                   RETURN;
-               }
                SETs(boolSV(auv <= (UV)biv));
                RETURN;
            }
@@ -1668,11 +1673,6 @@ PP(pp_le)
                }
                buv = SvUVX(TOPs);
                SP--;
-               if (buv >= (UV) IV_MAX) {
-                   /* As (a) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_yes);
-                   RETURN;
-               }
                SETs(boolSV((UV)aiv <= buv));
                RETURN;
            }
@@ -1725,11 +1725,6 @@ PP(pp_ge)
                    RETURN;
                }
                auv = SvUVX(TOPs);
-               if (auv >= (UV) IV_MAX) {
-                   /* As (b) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_yes);
-                   RETURN;
-               }
                SETs(boolSV(auv >= (UV)biv));
                RETURN;
            }
@@ -1746,11 +1741,6 @@ PP(pp_ge)
                }
                buv = SvUVX(TOPs);
                SP--;
-               if (buv > (UV) IV_MAX) {
-                   /* As (a) is an IV, it cannot be > IV_MAX */
-                   SETs(&PL_sv_no);
-                   RETURN;
-               }
                SETs(boolSV((UV)aiv >= buv));
                RETURN;
            }
@@ -1769,7 +1759,8 @@ PP(pp_ne)
     dSP; tryAMAGICbinSET(ne,0);
 #ifndef NV_PRESERVES_UV
     if (SvROK(TOPs) && SvROK(TOPm1s)) {
-       SETs(boolSV(SvRV(TOPs) != SvRV(TOPm1s)));
+        SP--;
+       SETs(boolSV(SvRV(TOPs) != SvRV(TOPp1s)));
        RETURN;
     }
 #endif
@@ -1822,11 +1813,6 @@ PP(pp_ne)
                    }
                    uv = SvUVX(*(SP+1)); /* Do I want TOPp1s() ? */
                }
-               /* we know iv is >= 0 */
-               if (uv > (UV) IV_MAX) {
-                   SETs(&PL_sv_yes);
-                   RETURN;
-               }
                SETs(boolSV((UV)iv != uv));
                RETURN;
            }
@@ -1845,7 +1831,9 @@ PP(pp_ncmp)
     dSP; dTARGET; tryAMAGICbin(ncmp,0);
 #ifndef NV_PRESERVES_UV
     if (SvROK(TOPs) && SvROK(TOPm1s)) {
-       SETi(PTR2UV(SvRV(TOPs)) - PTR2UV(SvRV(TOPm1s)));
+        UV right = PTR2UV(SvRV(POPs));
+        UV left = PTR2UV(SvRV(TOPs));
+       SETi((left > right) - (left < right));
        RETURN;
     }
 #endif
@@ -1888,10 +1876,7 @@ PP(pp_ncmp)
                    value = 1;
                } else {
                    leftuv = SvUVX(TOPm1s);
-                   if (leftuv > (UV) IV_MAX) {
-                       /* As (b) is an IV, it cannot be > IV_MAX */
-                       value = 1;
-                   } else if (leftuv > (UV)rightiv) {
+                   if (leftuv > (UV)rightiv) {
                        value = 1;
                    } else if (leftuv < (UV)rightiv) {
                        value = -1;
@@ -1909,12 +1894,9 @@ PP(pp_ncmp)
                    value = -1;
                } else {
                    rightuv = SvUVX(TOPs);
-                   if (rightuv > (UV) IV_MAX) {
-                       /* As (a) is an IV, it cannot be > IV_MAX */
-                       value = -1;
-                   } else if (leftiv > (UV)rightuv) {
+                   if ((UV)leftiv > rightuv) {
                        value = 1;
-                   } else if (leftiv < (UV)rightuv) {
+                   } else if ((UV)leftiv < rightuv) {
                        value = -1;
                    } else {
                        value = 0;
@@ -2154,15 +2136,22 @@ PP(pp_negate)
                sv_setsv(TARG, sv);
                *SvPV_force(TARG, len) = *s == '-' ? '+' : '-';
            }
-           else if (DO_UTF8(sv) && UTF8_IS_START(*s) && isIDFIRST_utf8((U8*)s)) {
-               sv_setpvn(TARG, "-", 1);
-               sv_catsv(TARG, sv);
+           else if (DO_UTF8(sv)) {
+               SvIV_please(sv);
+               if (SvIOK(sv))
+                   goto oops_its_an_int;
+               if (SvNOK(sv))
+                   sv_setnv(TARG, -SvNV(sv));
+               else {
+                   sv_setpvn(TARG, "-", 1);
+                   sv_catsv(TARG, sv);
+               }
            }
            else {
-             SvIV_please(sv);
-             if (SvIOK(sv))
-               goto oops_its_an_int;
-             sv_setnv(TARG, -SvNV(sv));
+               SvIV_please(sv);
+               if (SvIOK(sv))
+                 goto oops_its_an_int;
+               sv_setnv(TARG, -SvNV(sv));
            }
            SETTARG;
        }
@@ -3070,8 +3059,16 @@ PP(pp_ord)
     SV *argsv = POPs;
     STRLEN len;
     U8 *s = (U8*)SvPVx(argsv, len);
+    SV *tmpsv;
+
+    if (PL_encoding && !DO_UTF8(argsv)) {
+        tmpsv = sv_2mortal(newSVsv(argsv));
+        s = (U8*)Perl_sv_recode_to_utf8(aTHX_ tmpsv, PL_encoding);
+        argsv = tmpsv;
+    }
 
     XPUSHu(DO_UTF8(argsv) ? utf8_to_uvchr(s, 0) : (*s & 0xff));
+    
     RETURN;
 }
 
@@ -3100,6 +3097,8 @@ PP(pp_chr)
     *tmps++ = value;
     *tmps = '\0';
     (void)SvPOK_only(TARG);
+    if (PL_encoding)
+        Perl_sv_recode_to_utf8(aTHX_ TARG, PL_encoding);
     XPUSHs(TARG);
     RETURN;
 }
@@ -3146,34 +3145,27 @@ PP(pp_ucfirst)
     register U8 *s;
     STRLEN slen;
 
-    if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && UTF8_IS_START(*s)) {
+    if (DO_UTF8(sv)) {
+       U8 tmpbuf[UTF8_MAXLEN*2+1];
        STRLEN ulen;
-       U8 tmpbuf[UTF8_MAXLEN+1];
-       U8 *tend;
-       UV uv;
+       STRLEN tculen;
 
-       if (IN_LOCALE_RUNTIME) {
-           TAINT;
-           SvTAINTED_on(sv);
-           uv = toTITLE_LC_uvchr(utf8n_to_uvchr(s, slen, &ulen, 0));
-       }
-       else {
-           uv   = toTITLE_utf8(s);
-           ulen = UNISKIP(uv);
-       }
-       
-       tend = uvchr_to_utf8(tmpbuf, uv);
+       s = (U8*)SvPV(sv, slen);
+       utf8_to_uvchr(s, &ulen);
 
-       if (!SvPADTMP(sv) || tend - tmpbuf != ulen || SvREADONLY(sv)) {
+       toTITLE_utf8(s, tmpbuf, &tculen);
+       utf8_to_uvchr(tmpbuf, 0);
+
+       if (!SvPADTMP(sv) || SvREADONLY(sv)) {
            dTARGET;
-           sv_setpvn(TARG, (char*)tmpbuf, tend - tmpbuf);
+           sv_setpvn(TARG, (char*)tmpbuf, tculen);
            sv_catpvn(TARG, (char*)(s + ulen), slen - ulen);
            SvUTF8_on(TARG);
            SETs(TARG);
        }
        else {
            s = (U8*)SvPV_force(sv, slen);
-           Copy(tmpbuf, s, ulen, U8);
+           Copy(tmpbuf, s, tculen, U8);
        }
     }
     else {
@@ -3209,19 +3201,12 @@ PP(pp_lcfirst)
 
     if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && UTF8_IS_START(*s)) {
        STRLEN ulen;
-       U8 tmpbuf[UTF8_MAXLEN+1];
+       U8 tmpbuf[UTF8_MAXLEN*2+1];
        U8 *tend;
        UV uv;
 
-       if (IN_LOCALE_RUNTIME) {
-           TAINT;
-           SvTAINTED_on(sv);
-           uv = toLOWER_LC_uvchr(utf8n_to_uvchr(s, slen, &ulen, 0));
-       }
-       else {
-           uv   = toLOWER_utf8(s);
-           ulen = UNISKIP(uv);
-       }
+       toLOWER_utf8(s, tmpbuf, &ulen);
+       uv = utf8_to_uvchr(tmpbuf, 0);
        
        tend = uvchr_to_utf8(tmpbuf, uv);
 
@@ -3273,6 +3258,7 @@ PP(pp_uc)
        STRLEN ulen;
        register U8 *d;
        U8 *send;
+       U8 tmpbuf[UTF8_MAXLEN*2+1];
 
        s = (U8*)SvPV(sv,len);
        if (!len) {
@@ -3286,19 +3272,11 @@ PP(pp_uc)
            (void)SvPOK_only(TARG);
            d = (U8*)SvPVX(TARG);
            send = s + len;
-           if (IN_LOCALE_RUNTIME) {
-               TAINT;
-               SvTAINTED_on(TARG);
-               while (s < send) {
-                   d = uvchr_to_utf8(d, toUPPER_LC_uvchr( utf8n_to_uvchr(s, len, &ulen, 0)));
-                   s += ulen;
-               }
-           }
-           else {
-               while (s < send) {
-                   d = uvchr_to_utf8(d, toUPPER_utf8( s ));
-                   s += UTF8SKIP(s);
-               }
+           while (s < send) {
+               toUPPER_utf8(s, tmpbuf, &ulen);
+               Copy(tmpbuf, d, ulen, U8);
+               d += ulen;
+               s += UTF8SKIP(s);
            }
            *d = '\0';
            SvUTF8_on(TARG);
@@ -3347,6 +3325,7 @@ PP(pp_lc)
        STRLEN ulen;
        register U8 *d;
        U8 *send;
+       U8 tmpbuf[UTF8_MAXLEN*2+1];
 
        s = (U8*)SvPV(sv,len);
        if (!len) {
@@ -3360,19 +3339,28 @@ PP(pp_lc)
            (void)SvPOK_only(TARG);
            d = (U8*)SvPVX(TARG);
            send = s + len;
-           if (IN_LOCALE_RUNTIME) {
-               TAINT;
-               SvTAINTED_on(TARG);
-               while (s < send) {
-                   d = uvchr_to_utf8(d, toLOWER_LC_uvchr( utf8n_to_uvchr(s, len, &ulen, 0)));
-                   s += ulen;
-               }
-           }
-           else {
-               while (s < send) {
-                   d = uvchr_to_utf8(d, toLOWER_utf8(s));
-                   s += UTF8SKIP(s);
+           while (s < send) {
+               UV uv = toLOWER_utf8(s, tmpbuf, &ulen);
+#define GREEK_CAPITAL_LETTER_SIGMA 0x03A3 /* Unicode */
+               if (uv == GREEK_CAPITAL_LETTER_SIGMA) {
+                    /*
+                     * Now if the sigma is NOT followed by
+                     * /$ignorable_sequence$cased_letter/;
+                     * and it IS preceded by
+                     * /$cased_letter$ignorable_sequence/;
+                     * where $ignorable_sequence is
+                     * [\x{2010}\x{AD}\p{Mn}]*
+                     * and $cased_letter is
+                     * [\p{Ll}\p{Lo}\p{Lt}]
+                     * then it should be mapped to 0x03C2,
+                     * (GREEK SMALL LETTER FINAL SIGMA),
+                     * instead of staying 0x03A3.
+                     * See lib/unicore/SpecCase.txt.
+                     */
                }
+               Copy(tmpbuf, d, ulen, U8);
+               d += ulen;
+               s += UTF8SKIP(s);
            }
            *d = '\0';
            SvUTF8_on(TARG);
@@ -4199,7 +4187,7 @@ PP(pp_split)
 
     if (pm->op_pmreplroot) {
 #ifdef USE_ITHREADS
-       ary = GvAVn((GV*)PL_curpad[(PADOFFSET)pm->op_pmreplroot]);
+       ary = GvAVn((GV*)PL_curpad[INT2PTR(PADOFFSET, pm->op_pmreplroot)]);
 #else
        ary = GvAVn((GV*)pm->op_pmreplroot);
 #endif