X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp.c;h=eca00c8ec296d326ddcb4bae09802b4369acfa61;hb=7c36658b988154cf97fb44e48a4b69859fe075fb;hp=ae8cb6fdb88c2147ef2b95a40d6b1b14b9f11fab;hpb=4d1ff10ffec86208b0da135b87c76b89e61c866e;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp.c b/pp.c index ae8cb6f..eca00c8 100644 --- 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); @@ -1115,62 +1118,91 @@ PP(pp_modulo) UV right = 0; bool left_neg; bool right_neg; - bool use_double = 0; + bool use_double = FALSE; + bool dright_valid = FALSE; NV dright = 0.0; NV dleft = 0.0; - if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { - IV i = SvIVX(POPs); - right = (right_neg = (i < 0)) ? -i : i; - } - else { + SvIV_please(TOPs); + if (SvIOK(TOPs)) { + right_neg = !SvUOK(TOPs); + if (!right_neg) { + right = SvUVX(POPs); + } else { + IV biv = SvIVX(POPs); + if (biv >= 0) { + right = biv; + right_neg = FALSE; /* effectively it's a UV now */ + } else { + right = -biv; + } + } + } + else { dright = POPn; - use_double = 1; right_neg = dright < 0; if (right_neg) dright = -dright; + if (dright < UV_MAX_P1) { + right = U_V(dright); + dright_valid = TRUE; /* In case we need to use double below. */ + } else { + use_double = TRUE; + } } - if (!use_double && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { - IV i = SvIVX(POPs); - left = (left_neg = (i < 0)) ? -i : i; - } + /* At this point use_double is only true if right is out of range for + a UV. In range NV has been rounded down to nearest UV and + use_double false. */ + SvIV_please(TOPs); + if (!use_double && SvIOK(TOPs)) { + if (SvIOK(TOPs)) { + left_neg = !SvUOK(TOPs); + if (!left_neg) { + left = SvUVX(POPs); + } else { + IV aiv = SvIVX(POPs); + if (aiv >= 0) { + left = aiv; + left_neg = FALSE; /* effectively it's a UV now */ + } else { + left = -aiv; + } + } + } + } else { dleft = POPn; - if (!use_double) { - use_double = 1; - dright = right; - } left_neg = dleft < 0; if (left_neg) dleft = -dleft; - } + /* This should be exactly the 5.6 behaviour - if left and right are + both in range for UV then use U_V() rather than floor. */ + if (!use_double) { + if (dleft < UV_MAX_P1) { + /* right was in range, so is dleft, so use UVs not double. + */ + left = U_V(dleft); + } + /* left is out of range for UV, right was in range, so promote + right (back) to double. */ + else { + /* The +0.5 is used in 5.6 even though it is not strictly + consistent with the implicit +0 floor in the U_V() + inside the #if 1. */ + dleft = Perl_floor(dleft + 0.5); + use_double = TRUE; + if (dright_valid) + dright = Perl_floor(dright + 0.5); + else + dright = right; + } + } + } if (use_double) { NV dans; -#if 1 -/* Somehow U_V is pessimized even if CASTFLAGS is 0 */ -# if CASTFLAGS & 2 -# define CAST_D2UV(d) U_V(d) -# else -# define CAST_D2UV(d) ((UV)(d)) -# endif - /* Tried to do this only in the case DOUBLESIZE <= UV_SIZE, - * or, in other words, precision of UV more than of NV. - * But in fact the approach below turned out to be an - * optimization - floor() may be slow */ - if (dright <= UV_MAX && dleft <= UV_MAX) { - right = CAST_D2UV(dright); - left = CAST_D2UV(dleft); - goto do_uv; - } -#endif - - /* Backward-compatibility clause: */ - dright = Perl_floor(dright + 0.5); - dleft = Perl_floor(dleft + 0.5); - if (!dright) DIE(aTHX_ "Illegal modulus zero"); @@ -1184,7 +1216,6 @@ PP(pp_modulo) else { UV ans; - do_uv: if (!right) DIE(aTHX_ "Illegal modulus zero"); @@ -2699,40 +2730,54 @@ PP(pp_abs) RETURN; } + PP(pp_hex) { dSP; dTARGET; char *tmps; - STRLEN argtype; + I32 flags = PERL_SCAN_ALLOW_UNDERSCORES; STRLEN len; + NV result_nv; + UV result_uv; tmps = (SvPVx(POPs, len)); - argtype = 1; /* allow underscores */ - XPUSHn(scan_hex(tmps, len, &argtype)); + result_uv = grok_hex (tmps, &len, &flags, &result_nv); + if (flags & PERL_SCAN_GREATER_THAN_UV_MAX) { + XPUSHn(result_nv); + } + else { + XPUSHu(result_uv); + } RETURN; } PP(pp_oct) { dSP; dTARGET; - NV value; - STRLEN argtype; char *tmps; + I32 flags = PERL_SCAN_ALLOW_UNDERSCORES; STRLEN len; + NV result_nv; + UV result_uv; tmps = (SvPVx(POPs, len)); while (*tmps && len && isSPACE(*tmps)) - tmps++, len--; + tmps++, len--; if (*tmps == '0') - tmps++, len--; - argtype = 1; /* allow underscores */ + tmps++, len--; if (*tmps == 'x') - value = scan_hex(++tmps, --len, &argtype); + result_uv = grok_hex (tmps, &len, &flags, &result_nv); else if (*tmps == 'b') - value = scan_bin(++tmps, --len, &argtype); + result_uv = grok_bin (tmps, &len, &flags, &result_nv); else - value = scan_oct(tmps, len, &argtype); - XPUSHn(value); + result_uv = grok_oct (tmps, &len, &flags, &result_nv); + + if (flags & PERL_SCAN_GREATER_THAN_UV_MAX) { + XPUSHn(result_nv); + } + else { + XPUSHu(result_uv); + } RETURN; } @@ -3067,12 +3112,28 @@ PP(pp_crypt) dSP; dTARGET; dPOPTOPssrl; STRLEN n_a; #ifdef HAS_CRYPT - char *tmps = SvPV(left, n_a); + STRLEN len; + char *tmps = SvPV(left, len); + char *t = 0; + if (DO_UTF8(left)) { + /* If Unicode take the crypt() of the low 8 bits + * of the characters of the string. */ + char *s = tmps; + char *send = tmps + len; + STRLEN i = 0; + Newz(688, t, len, char); + while (s < send) { + t[i++] = utf8_to_uvchr((U8*)s, 0) & 0xFF; + s += UTF8SKIP(s); + } + tmps = t; + } #ifdef FCRYPT sv_setpv(TARG, fcrypt(tmps, SvPV(right, n_a))); #else sv_setpv(TARG, PerlProc_crypt(tmps, SvPV(right, n_a))); #endif + Safefree(t); #else DIE(aTHX_ "The crypt() function is unimplemented due to excessive paranoia."); @@ -4137,11 +4198,11 @@ PP(pp_split) TAINT_IF((pm->op_pmflags & PMf_LOCALE) && (pm->op_pmflags & (PMf_WHITE | PMf_SKIPWHITE))); - PL_reg_sv_utf8 = do_utf8; + PL_reg_match_utf8 = do_utf8; 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