X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp.c;h=773626fd7f4931dddaf9ceb8edb6a25de6025b64;hb=33c0e3ec3c9b4103fd0146ace1e9048f01c2013d;hp=d837d4b9d1ac027f886c89156a415e858bf20d16;hpb=79cb57f6e01f91d8fff40d69caa187aaa669671b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp.c b/pp.c index d837d4b..773626f 100644 --- a/pp.c +++ b/pp.c @@ -13,6 +13,7 @@ */ #include "EXTERN.h" +#define PERL_IN_PP_C #include "perl.h" /* @@ -110,12 +111,6 @@ typedef unsigned UBW; # define CAT32(sv,p) sv_catpvn(sv, (char*)(p), SIZE32) #endif -#ifndef PERL_OBJECT -static void doencodes _((SV* sv, char* s, I32 len)); -static SV* refto _((SV* sv)); -static U32 seed _((void)); -#endif - /* variations on pp_null */ #ifdef I_UNISTD @@ -191,12 +186,12 @@ PP(pp_padhv) RETURN; gimme = GIMME_V; if (gimme == G_ARRAY) { - RETURNOP(do_kv(ARGS)); + RETURNOP(do_kv()); } else if (gimme == G_SCALAR) { SV* sv = sv_newmortal(); if (HvFILL((HV*)TARG)) - sv_setpvf(sv, "%ld/%ld", + Perl_sv_setpvf(aTHX_ sv, "%ld/%ld", (long)HvFILL((HV*)TARG), (long)HvMAX((HV*)TARG) + 1); else sv_setiv(sv, 0); @@ -207,14 +202,14 @@ PP(pp_padhv) PP(pp_padany) { - DIE("NOT IMPL LINE %d",__LINE__); + DIE(aTHX_ "NOT IMPL LINE %d",__LINE__); } /* Translations. */ PP(pp_rv2gv) { - djSP; dTOPss; + djSP; dTOPss; if (SvROK(sv)) { wasref: @@ -229,7 +224,7 @@ PP(pp_rv2gv) sv = (SV*) gv; } else if (SvTYPE(sv) != SVt_PVGV) - DIE("Not a GLOB reference"); + DIE(aTHX_ "Not a GLOB reference"); } else { if (SvTYPE(sv) != SVt_PVGV) { @@ -242,11 +237,29 @@ PP(pp_rv2gv) goto wasref; } if (!SvOK(sv)) { + /* If this is a 'my' scalar and flag is set then vivify + * NI-S 1999/05/07 + */ + if (PL_op->op_private & OPpDEREF) { + GV *gv = (GV *) newSV(0); + STRLEN len = 0; + char *name = ""; + if (cUNOP->op_first->op_type == OP_PADSV) { + SV *padname = *av_fetch(PL_comppad_name, cUNOP->op_first->op_targ, 4); + name = SvPV(padname,len); + } + gv_init(gv, PL_curcop->cop_stash, name, len, 0); + sv_upgrade(sv, SVt_RV); + SvRV(sv) = (SV *) gv; + SvROK_on(sv); + SvSETMAGIC(sv); + goto wasref; + } if (PL_op->op_flags & OPf_REF || PL_op->op_private & HINT_STRICT_REFS) - DIE(PL_no_usym, "a symbol"); + DIE(aTHX_ PL_no_usym, "a symbol"); if (ckWARN(WARN_UNINITIALIZED)) - warner(WARN_UNINITIALIZED, PL_warn_uninit); + Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit); RETSETUNDEF; } sym = SvPV(sv, n_a); @@ -259,7 +272,7 @@ PP(pp_rv2gv) } else { if (PL_op->op_private & HINT_STRICT_REFS) - DIE(PL_no_symref, sym, "a symbol"); + DIE(aTHX_ PL_no_symref, sym, "a symbol"); sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV); } } @@ -283,7 +296,7 @@ PP(pp_rv2sv) case SVt_PVAV: case SVt_PVHV: case SVt_PVCV: - DIE("Not a SCALAR reference"); + DIE(aTHX_ "Not a SCALAR reference"); } } else { @@ -300,9 +313,9 @@ PP(pp_rv2sv) if (!SvOK(sv)) { if (PL_op->op_flags & OPf_REF || PL_op->op_private & HINT_STRICT_REFS) - DIE(PL_no_usym, "a SCALAR"); + DIE(aTHX_ PL_no_usym, "a SCALAR"); if (ckWARN(WARN_UNINITIALIZED)) - warner(WARN_UNINITIALIZED, PL_warn_uninit); + Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit); RETSETUNDEF; } sym = SvPV(sv, n_a); @@ -315,7 +328,7 @@ PP(pp_rv2sv) } else { if (PL_op->op_private & HINT_STRICT_REFS) - DIE(PL_no_symref, sym, "a SCALAR"); + DIE(aTHX_ PL_no_symref, sym, "a SCALAR"); gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV); } } @@ -393,6 +406,8 @@ PP(pp_rv2cv) if (cv) { if (CvCLONE(cv)) cv = (CV*)sv_2mortal((SV*)cv_clone(cv)); + if ((PL_op->op_private & OPpLVAL_INTRO) && !CvLVALUE(cv)) + Perl_croak(aTHX_ "Can't modify non-lvalue subroutine call"); } else cv = (CV*)&PL_sv_undef; @@ -454,7 +469,7 @@ PP(pp_prototype) goto set; else { /* None such */ nonesuch: - croak("Cannot find an opnumber for \"%s\"", s+6); + Perl_croak(aTHX_ "Can't find an opnumber for \"%s\"", s+6); } } } @@ -503,7 +518,7 @@ PP(pp_refgen) } STATIC SV* -refto(SV *sv) +S_refto(pTHX_ SV *sv) { SV* rv; @@ -512,6 +527,14 @@ refto(SV *sv) vivify_defelem(sv); if (!(sv = LvTARG(sv))) sv = &PL_sv_undef; + else + (void)SvREFCNT_inc(sv); + } + else if (SvTYPE(sv) == SVt_PVAV) { + if (!AvREAL((AV*)sv) && AvREIFY((AV*)sv)) + av_reify((AV*)sv); + SvTEMP_off(sv); + (void)SvREFCNT_inc(sv); } else if (SvPADTMP(sv)) sv = newSVsv(sv); @@ -558,7 +581,7 @@ PP(pp_bless) STRLEN len; char *ptr = SvPV(ssv,len); if (ckWARN(WARN_UNSAFE) && len == 0) - warner(WARN_UNSAFE, + Perl_warner(aTHX_ WARN_UNSAFE, "Explicit blessing to '' (assuming package main)"); stash = gv_stashpvn(ptr, len, TRUE); } @@ -635,7 +658,6 @@ PP(pp_gelem) PP(pp_study) { djSP; dPOPss; - register UNOP *unop = cUNOP; register unsigned char *s; register I32 pos; register I32 ch; @@ -675,7 +697,7 @@ PP(pp_study) snext = PL_screamnext; if (!sfirst || !snext) - DIE("do_study: out of memory"); + DIE(aTHX_ "do_study: out of memory"); for (ch = 256; ch; --ch) *sfirst++ = -1; @@ -806,7 +828,7 @@ PP(pp_undef) break; case SVt_PVCV: if (ckWARN(WARN_UNSAFE) && cv_const_sv((CV*)sv)) - warner(WARN_UNSAFE, "Constant subroutine %s undefined", + Perl_warner(aTHX_ WARN_UNSAFE, "Constant subroutine %s undefined", CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv))); /* FALL THROUGH */ case SVt_PVFM: @@ -849,8 +871,8 @@ PP(pp_predec) { djSP; if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) - croak(PL_no_modify); - if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && + Perl_croak(aTHX_ PL_no_modify); + if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MIN) { --SvIVX(TOPs); @@ -866,9 +888,9 @@ PP(pp_postinc) { djSP; dTARGET; if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) - croak(PL_no_modify); + Perl_croak(aTHX_ PL_no_modify); sv_setsv(TARG, TOPs); - if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && + if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MAX) { ++SvIVX(TOPs); @@ -886,10 +908,10 @@ PP(pp_postinc) PP(pp_postdec) { djSP; dTARGET; - if(SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) - croak(PL_no_modify); + if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) + Perl_croak(aTHX_ PL_no_modify); sv_setsv(TARG, TOPs); - if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && + if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MIN) { --SvIVX(TOPs); @@ -929,15 +951,15 @@ PP(pp_divide) djSP; dATARGET; tryAMAGICbin(div,opASSIGN); { dPOPPOPnnrl; - double value; + NV value; if (right == 0.0) - DIE("Illegal division by zero"); + DIE(aTHX_ "Illegal division by zero"); #ifdef SLOPPYDIVIDE /* insure that 20./5. == 4. */ { IV k; - if ((double)I_V(left) == left && - (double)I_V(right) == right && + if ((NV)I_V(left) == left && + (NV)I_V(right) == right && (k = I_V(left)/I_V(right))*I_V(right) == I_V(left)) { value = k; } @@ -957,48 +979,99 @@ PP(pp_modulo) { djSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); { - UV left; - UV right; - bool left_neg; - bool right_neg; - UV ans; - - if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { - IV i = SvIVX(POPs); - right = (right_neg = (i < 0)) ? -i : i; - } - else { - double n = POPn; - right = U_V((right_neg = (n < 0)) ? -n : n); - } + UV left; + UV right; + bool left_neg; + bool right_neg; + bool use_double = 0; + NV dright; + NV dleft; + + if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { + IV i = SvIVX(POPs); + right = (right_neg = (i < 0)) ? -i : i; + } + else { + dright = POPn; + use_double = 1; + right_neg = dright < 0; + if (right_neg) + dright = -dright; + } - if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { - IV i = SvIVX(POPs); - left = (left_neg = (i < 0)) ? -i : i; - } - else { - double n = POPn; - left = U_V((left_neg = (n < 0)) ? -n : n); - } + if (!use_double && SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) { + IV i = SvIVX(POPs); + left = (left_neg = (i < 0)) ? -i : i; + } + else { + dleft = POPn; + if (!use_double) { + use_double = 1; + dright = right; + } + left_neg = dleft < 0; + if (left_neg) + dleft = -dleft; + } - if (!right) - DIE("Illegal modulus zero"); - - ans = left % right; - if ((left_neg != right_neg) && ans) - ans = right - ans; - if (right_neg) { - /* XXX may warn: unary minus operator applied to unsigned type */ - /* could change -foo to be (~foo)+1 instead */ - if (ans <= ~((UV)IV_MAX)+1) - sv_setiv(TARG, ~ans+1); - else - sv_setnv(TARG, -(double)ans); - } - else - sv_setuv(TARG, ans); - PUSHTARG; - RETURN; + 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 = floor(dright + 0.5); + dleft = floor(dleft + 0.5); + + if (!dright) + DIE(aTHX_ "Illegal modulus zero"); + + dans = Perl_fmod(dleft, dright); + if ((left_neg != right_neg) && dans) + dans = dright - dans; + if (right_neg) + dans = -dans; + sv_setnv(TARG, dans); + } + else { + UV ans; + + do_uv: + if (!right) + DIE(aTHX_ "Illegal modulus zero"); + + ans = left % right; + if ((left_neg != right_neg) && ans) + ans = right - ans; + if (right_neg) { + /* XXX may warn: unary minus operator applied to unsigned type */ + /* could change -foo to be (~foo)+1 instead */ + if (ans <= ~((UV)IV_MAX)+1) + sv_setiv(TARG, ~ans+1); + else + sv_setnv(TARG, -(NV)ans); + } + else + sv_setuv(TARG, ans); + } + PUSHTARG; + RETURN; } } @@ -1428,7 +1501,7 @@ PP(pp_i_divide) { dPOPiv; if (value == 0) - DIE("Illegal division by zero"); + DIE(aTHX_ "Illegal division by zero"); value = POPi / value; PUSHi( value ); RETURN; @@ -1441,7 +1514,7 @@ PP(pp_i_modulo) { dPOPTOPiirl; if (!right) - DIE("Illegal modulus zero"); + DIE(aTHX_ "Illegal modulus zero"); SETi( left % right ); RETURN; } @@ -1559,7 +1632,7 @@ PP(pp_atan2) djSP; dTARGET; tryAMAGICbin(atan2,0); { dPOPTOPnnrl; - SETn(atan2(left, right)); + SETn(Perl_atan2(left, right)); RETURN; } } @@ -1568,9 +1641,9 @@ PP(pp_sin) { djSP; dTARGET; tryAMAGICun(sin); { - double value; + NV value; value = POPn; - value = sin(value); + value = Perl_sin(value); XPUSHn(value); RETURN; } @@ -1580,9 +1653,9 @@ PP(pp_cos) { djSP; dTARGET; tryAMAGICun(cos); { - double value; + NV value; value = POPn; - value = cos(value); + value = Perl_cos(value); XPUSHn(value); RETURN; } @@ -1600,13 +1673,13 @@ PP(pp_cos) */ #ifndef HAS_DRAND48_PROTO -extern double drand48 _((void)); +extern double drand48 (void); #endif PP(pp_rand) { djSP; dTARGET; - double value; + NV value; if (MAXARG < 1) value = 1.0; else @@ -1637,7 +1710,7 @@ PP(pp_srand) } STATIC U32 -seed(void) +S_seed(pTHX) { /* * This is really just a quick hack which grabs various garbage @@ -1711,9 +1784,9 @@ seed(void) # endif #endif u += SEED_C3 * (U32)getpid(); - u += SEED_C4 * (U32)(UV)PL_stack_sp; + u += SEED_C4 * (U32)PTR2UV(PL_stack_sp); #ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */ - u += SEED_C5 * (U32)(UV)&when; + u += SEED_C5 * (U32)PTR2UV(&when); #endif return u; } @@ -1722,9 +1795,9 @@ PP(pp_exp) { djSP; dTARGET; tryAMAGICun(exp); { - double value; + NV value; value = POPn; - value = exp(value); + value = Perl_exp(value); XPUSHn(value); RETURN; } @@ -1734,13 +1807,13 @@ PP(pp_log) { djSP; dTARGET; tryAMAGICun(log); { - double value; + NV value; value = POPn; if (value <= 0.0) { - SET_NUMERIC_STANDARD(); - DIE("Can't take log of %g", value); + RESTORE_NUMERIC_STANDARD(); + DIE(aTHX_ "Can't take log of %g", value); } - value = log(value); + value = Perl_log(value); XPUSHn(value); RETURN; } @@ -1750,13 +1823,13 @@ PP(pp_sqrt) { djSP; dTARGET; tryAMAGICun(sqrt); { - double value; + NV value; value = POPn; if (value < 0.0) { - SET_NUMERIC_STANDARD(); - DIE("Can't take sqrt of %g", value); + RESTORE_NUMERIC_STANDARD(); + DIE(aTHX_ "Can't take sqrt of %g", value); } - value = sqrt(value); + value = Perl_sqrt(value); XPUSHn(value); RETURN; } @@ -1766,7 +1839,7 @@ PP(pp_int) { djSP; dTARGET; { - double value = TOPn; + NV value = TOPn; IV iv; if (SvIOKp(TOPs) && !SvNOKp(TOPs) && !SvPOKp(TOPs)) { @@ -1775,9 +1848,9 @@ PP(pp_int) } else { if (value >= 0.0) - (void)modf(value, &value); + (void)Perl_modf(value, &value); else { - (void)modf(-value, &value); + (void)Perl_modf(-value, &value); value = -value; } iv = I_V(value); @@ -1794,7 +1867,7 @@ PP(pp_abs) { djSP; dTARGET; tryAMAGICun(abs); { - double value = TOPn; + NV value = TOPn; IV iv; if (SvIOKp(TOPs) && !SvNOKp(TOPs) && !SvPOKp(TOPs) && @@ -1820,14 +1893,14 @@ PP(pp_hex) STRLEN n_a; tmps = POPpx; - XPUSHu(scan_hex(tmps, 99, &argtype)); + XPUSHn(scan_hex(tmps, 99, &argtype)); RETURN; } PP(pp_oct) { djSP; dTARGET; - UV value; + NV value; I32 argtype; char *tmps; STRLEN n_a; @@ -1843,7 +1916,7 @@ PP(pp_oct) value = scan_bin(++tmps, 99, &argtype); else value = scan_oct(tmps, 99, &argtype); - XPUSHu(value); + XPUSHn(value); RETURN; } @@ -1935,7 +2008,7 @@ PP(pp_substr) } if (fail < 0) { if (ckWARN(WARN_SUBSTR) || lvalue || repl) - warner(WARN_SUBSTR, "substr outside of string"); + Perl_warner(aTHX_ WARN_SUBSTR, "substr outside of string"); RETPUSHUNDEF; } else { @@ -1949,7 +2022,7 @@ PP(pp_substr) STRLEN n_a; SvPV_force(sv,n_a); if (ckWARN(WARN_SUBSTR)) - warner(WARN_SUBSTR, + Perl_warner(aTHX_ WARN_SUBSTR, "Attempt to use reference as lvalue in substr"); } if (SvOK(sv)) /* is it defined ? */ @@ -1987,74 +2060,24 @@ PP(pp_vec) register I32 offset = POPi; register SV *src = POPs; I32 lvalue = PL_op->op_flags & OPf_MOD; - STRLEN srclen; - unsigned char *s = (unsigned char*)SvPV(src, srclen); - unsigned long retnum; - I32 len; - - SvTAINTED_off(TARG); /* decontaminate */ - offset *= size; /* turn into bit offset */ - len = (offset + size + 7) / 8; - if (offset < 0 || size < 1) - retnum = 0; - else { - if (lvalue) { /* it's an lvalue! */ - if (SvTYPE(TARG) < SVt_PVLV) { - sv_upgrade(TARG, SVt_PVLV); - sv_magic(TARG, Nullsv, 'v', Nullch, 0); - } - LvTYPE(TARG) = 'v'; - if (LvTARG(TARG) != src) { - if (LvTARG(TARG)) - SvREFCNT_dec(LvTARG(TARG)); - LvTARG(TARG) = SvREFCNT_inc(src); - } - LvTARGOFF(TARG) = offset; - LvTARGLEN(TARG) = size; - } - if (len > srclen) { - if (size <= 8) - retnum = 0; - else { - offset >>= 3; - if (size == 16) { - if (offset >= srclen) - retnum = 0; - else - retnum = (unsigned long) s[offset] << 8; - } - else if (size == 32) { - if (offset >= srclen) - retnum = 0; - else if (offset + 1 >= srclen) - retnum = (unsigned long) s[offset] << 24; - else if (offset + 2 >= srclen) - retnum = ((unsigned long) s[offset] << 24) + - ((unsigned long) s[offset + 1] << 16); - else - retnum = ((unsigned long) s[offset] << 24) + - ((unsigned long) s[offset + 1] << 16) + - (s[offset + 2] << 8); - } - } + SvTAINTED_off(TARG); /* decontaminate */ + if (lvalue) { /* it's an lvalue! */ + if (SvTYPE(TARG) < SVt_PVLV) { + sv_upgrade(TARG, SVt_PVLV); + sv_magic(TARG, Nullsv, 'v', Nullch, 0); } - else if (size < 8) - retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1); - else { - offset >>= 3; - if (size == 8) - retnum = s[offset]; - else if (size == 16) - retnum = ((unsigned long) s[offset] << 8) + s[offset+1]; - else if (size == 32) - retnum = ((unsigned long) s[offset] << 24) + - ((unsigned long) s[offset + 1] << 16) + - (s[offset + 2] << 8) + s[offset+3]; + LvTYPE(TARG) = 'v'; + if (LvTARG(TARG) != src) { + if (LvTARG(TARG)) + SvREFCNT_dec(LvTARG(TARG)); + LvTARG(TARG) = SvREFCNT_inc(src); } + LvTARGOFF(TARG) = offset; + LvTARGLEN(TARG) = size; } - sv_setuv(TARG, (UV)retnum); + sv_setuv(TARG, do_vecget(src, offset, size)); PUSHs(TARG); RETURN; } @@ -2139,12 +2162,6 @@ PP(pp_rindex) PP(pp_sprintf) { djSP; dMARK; dORIGMARK; dTARGET; -#ifdef USE_LOCALE_NUMERIC - if (PL_op->op_private & OPpLOCALE) - SET_NUMERIC_LOCAL(); - else - SET_NUMERIC_STANDARD(); -#endif do_sprintf(TARG, SP-MARK, MARK+1); TAINT_IF(SvTAINTED(TARG)); SP = ORIGMARK; @@ -2209,7 +2226,7 @@ PP(pp_crypt) sv_setpv(TARG, PerlProc_crypt(tmps, SvPV(right, n_a))); #endif #else - DIE( + DIE(aTHX_ "The crypt() function is unimplemented due to excessive paranoia."); #endif SETs(TARG); @@ -2249,26 +2266,27 @@ PP(pp_ucfirst) s = (U8*)SvPV_force(sv, slen); Copy(tmpbuf, s, ulen, U8); } - RETURN; } - - if (!SvPADTMP(sv)) { - dTARGET; - sv_setsv(TARG, sv); - sv = TARG; - SETs(sv); - } - s = (U8*)SvPV_force(sv, slen); - if (*s) { - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(sv); - *s = toUPPER_LC(*s); + else { + if (!SvPADTMP(sv)) { + dTARGET; + sv_setsv(TARG, sv); + sv = TARG; + SETs(sv); + } + s = (U8*)SvPV_force(sv, slen); + if (*s) { + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(sv); + *s = toUPPER_LC(*s); + } + else + *s = toUPPER(*s); } - else - *s = toUPPER(*s); } - + if (SvSMAGICAL(sv)) + mg_set(sv); RETURN; } @@ -2305,27 +2323,28 @@ PP(pp_lcfirst) s = (U8*)SvPV_force(sv, slen); Copy(tmpbuf, s, ulen, U8); } - RETURN; - } - - if (!SvPADTMP(sv)) { - dTARGET; - sv_setsv(TARG, sv); - sv = TARG; - SETs(sv); } - s = (U8*)SvPV_force(sv, slen); - if (*s) { - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(sv); - *s = toLOWER_LC(*s); + else { + if (!SvPADTMP(sv)) { + dTARGET; + sv_setsv(TARG, sv); + sv = TARG; + SETs(sv); } - else - *s = toLOWER(*s); + s = (U8*)SvPV_force(sv, slen); + if (*s) { + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(sv); + *s = toLOWER_LC(*s); + } + else + *s = toLOWER(*s); + } + SETs(sv); } - - SETs(sv); + if (SvSMAGICAL(sv)) + mg_set(sv); RETURN; } @@ -2346,56 +2365,57 @@ PP(pp_uc) if (!len) { sv_setpvn(TARG, "", 0); SETs(TARG); - RETURN; - } - - (void)SvUPGRADE(TARG, SVt_PV); - SvGROW(TARG, (len * 2) + 1); - (void)SvPOK_only(TARG); - d = (U8*)SvPVX(TARG); - send = s + len; - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(TARG); - while (s < send) { - d = uv_to_utf8(d, toUPPER_LC_uni( utf8_to_uv(s, &ulen))); - s += ulen; - } } else { - while (s < send) { - d = uv_to_utf8(d, toUPPER_utf8( s )); - s += UTF8SKIP(s); + (void)SvUPGRADE(TARG, SVt_PV); + SvGROW(TARG, (len * 2) + 1); + (void)SvPOK_only(TARG); + d = (U8*)SvPVX(TARG); + send = s + len; + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(TARG); + while (s < send) { + d = uv_to_utf8(d, toUPPER_LC_uni( utf8_to_uv(s, &ulen))); + s += ulen; + } } + else { + while (s < send) { + d = uv_to_utf8(d, toUPPER_utf8( s )); + s += UTF8SKIP(s); + } + } + *d = '\0'; + SvCUR_set(TARG, d - (U8*)SvPVX(TARG)); + SETs(TARG); } - *d = '\0'; - SvCUR_set(TARG, d - (U8*)SvPVX(TARG)); - SETs(TARG); - RETURN; - } - - if (!SvPADTMP(sv)) { - dTARGET; - sv_setsv(TARG, sv); - sv = TARG; - SETs(sv); } - - s = (U8*)SvPV_force(sv, len); - if (len) { - register U8 *send = s + len; - - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(sv); - for (; s < send; s++) - *s = toUPPER_LC(*s); + else { + if (!SvPADTMP(sv)) { + dTARGET; + sv_setsv(TARG, sv); + sv = TARG; + SETs(sv); } - else { - for (; s < send; s++) - *s = toUPPER(*s); + s = (U8*)SvPV_force(sv, len); + if (len) { + register U8 *send = s + len; + + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(sv); + for (; s < send; s++) + *s = toUPPER_LC(*s); + } + else { + for (; s < send; s++) + *s = toUPPER(*s); + } } } + if (SvSMAGICAL(sv)) + mg_set(sv); RETURN; } @@ -2416,56 +2436,58 @@ PP(pp_lc) if (!len) { sv_setpvn(TARG, "", 0); SETs(TARG); - RETURN; - } - - (void)SvUPGRADE(TARG, SVt_PV); - SvGROW(TARG, (len * 2) + 1); - (void)SvPOK_only(TARG); - d = (U8*)SvPVX(TARG); - send = s + len; - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(TARG); - while (s < send) { - d = uv_to_utf8(d, toLOWER_LC_uni( utf8_to_uv(s, &ulen))); - s += ulen; - } } else { - while (s < send) { - d = uv_to_utf8(d, toLOWER_utf8(s)); - s += UTF8SKIP(s); + (void)SvUPGRADE(TARG, SVt_PV); + SvGROW(TARG, (len * 2) + 1); + (void)SvPOK_only(TARG); + d = (U8*)SvPVX(TARG); + send = s + len; + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(TARG); + while (s < send) { + d = uv_to_utf8(d, toLOWER_LC_uni( utf8_to_uv(s, &ulen))); + s += ulen; + } + } + else { + while (s < send) { + d = uv_to_utf8(d, toLOWER_utf8(s)); + s += UTF8SKIP(s); + } } + *d = '\0'; + SvCUR_set(TARG, d - (U8*)SvPVX(TARG)); + SETs(TARG); } - *d = '\0'; - SvCUR_set(TARG, d - (U8*)SvPVX(TARG)); - SETs(TARG); - RETURN; } + else { + if (!SvPADTMP(sv)) { + dTARGET; + sv_setsv(TARG, sv); + sv = TARG; + SETs(sv); + } - if (!SvPADTMP(sv)) { - dTARGET; - sv_setsv(TARG, sv); - sv = TARG; - SETs(sv); - } + s = (U8*)SvPV_force(sv, len); + if (len) { + register U8 *send = s + len; - s = (U8*)SvPV_force(sv, len); - if (len) { - register U8 *send = s + len; - - if (PL_op->op_private & OPpLOCALE) { - TAINT; - SvTAINTED_on(sv); - for (; s < send; s++) - *s = toLOWER_LC(*s); - } - else { - for (; s < send; s++) - *s = toLOWER(*s); + if (PL_op->op_private & OPpLOCALE) { + TAINT; + SvTAINTED_on(sv); + for (; s < send; s++) + *s = toLOWER_LC(*s); + } + else { + for (; s < send; s++) + *s = toLOWER(*s); + } } } + if (SvSMAGICAL(sv)) + mg_set(sv); RETURN; } @@ -2513,6 +2535,8 @@ PP(pp_quotemeta) else sv_setpvn(TARG, s, len); SETs(TARG); + if (SvSMAGICAL(TARG)) + mg_set(TARG); RETURN; } @@ -2546,7 +2570,7 @@ PP(pp_aslice) svp = av_fetch(av, elem, lval); if (lval) { if (!svp || *svp == &PL_sv_undef) - DIE(PL_no_aelem, elem); + DIE(aTHX_ PL_no_aelem, elem); if (PL_op->op_private & OPpLVAL_INTRO) save_aelem(av, elem, svp); } @@ -2565,7 +2589,7 @@ PP(pp_aslice) PP(pp_each) { - djSP; dTARGET; + djSP; HV *hash = (HV*)POPs; HE *entry; I32 gimme = GIMME_V; @@ -2580,12 +2604,13 @@ PP(pp_each) if (entry) { PUSHs(hv_iterkeysv(entry)); /* won't clobber stack_sp */ if (gimme == G_ARRAY) { + SV *val; PUTBACK; /* might clobber stack_sp */ - sv_setsv(TARG, realhv ? - hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry)); + val = realhv ? + hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry); SPAGAIN; - PUSHs(TARG); + PUSHs(val); } } else if (gimme == G_SCALAR) @@ -2596,12 +2621,12 @@ PP(pp_each) PP(pp_values) { - return do_kv(ARGS); + return do_kv(); } PP(pp_keys) { - return do_kv(ARGS); + return do_kv(); } PP(pp_delete) @@ -2621,7 +2646,7 @@ PP(pp_delete) if (hvtype == SVt_PVHV) sv = hv_delete_ent(hv, *MARK, discard, 0); else - DIE("Not a HASH reference"); + DIE(aTHX_ "Not a HASH reference"); *MARK = sv ? sv : &PL_sv_undef; } if (discard) @@ -2638,7 +2663,7 @@ PP(pp_delete) if (SvTYPE(hv) == SVt_PVHV) sv = hv_delete_ent(hv, keysv, discard, 0); else - DIE("Not a HASH reference"); + DIE(aTHX_ "Not a HASH reference"); if (!sv) sv = &PL_sv_undef; if (!discard) @@ -2661,7 +2686,7 @@ PP(pp_exists) RETPUSHYES; } else { - DIE("Not a HASH reference"); + DIE(aTHX_ "Not a HASH reference"); } RETPUSHNO; } @@ -2674,7 +2699,7 @@ PP(pp_hslice) I32 realhv = (SvTYPE(hv) == SVt_PVHV); if (!realhv && PL_op->op_private & OPpLVAL_INTRO) - DIE("Can't localize pseudo-hash element"); + DIE(aTHX_ "Can't localize pseudo-hash element"); if (realhv || SvTYPE(hv) == SVt_PVAV) { while (++MARK <= SP) { @@ -2690,7 +2715,7 @@ PP(pp_hslice) if (lval) { if (!svp || *svp == &PL_sv_undef) { STRLEN n_a; - DIE(PL_no_helem, SvPV(keysv, n_a)); + DIE(aTHX_ PL_no_helem, SvPV(keysv, n_a)); } if (PL_op->op_private & OPpLVAL_INTRO) save_helem(hv, keysv, svp); @@ -2757,20 +2782,17 @@ PP(pp_lslice) for (lelem = firstlelem; lelem <= lastlelem; lelem++) { ix = SvIVx(*lelem); - if (ix < 0) { + if (ix < 0) ix += max; - if (ix < 0) - *lelem = &PL_sv_undef; - else if (!(*lelem = firstrelem[ix])) - *lelem = &PL_sv_undef; - } - else { + else ix -= arybase; - if (ix >= max || !(*lelem = firstrelem[ix])) + if (ix < 0 || ix >= max) + *lelem = &PL_sv_undef; + else { + is_something_there = TRUE; + if (!(*lelem = firstrelem[ix])) *lelem = &PL_sv_undef; } - if (!is_something_there && (SvOK(*lelem) || SvGMAGICAL(*lelem))) - is_something_there = TRUE; } if (is_something_there) SP = lastlelem; @@ -2800,7 +2822,7 @@ PP(pp_anonhash) if (MARK < SP) sv_setsv(val, *++MARK); else if (ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE, "Odd number of elements in hash assignment"); + Perl_warner(aTHX_ WARN_UNSAFE, "Odd number of elements in hash assignment"); (void)hv_store_ent(hv,key,val,0); } SP = ORIGMARK; @@ -2828,7 +2850,7 @@ PP(pp_splice) PUSHMARK(MARK); PUTBACK; ENTER; - perl_call_method("SPLICE",GIMME_V); + call_method("SPLICE",GIMME_V); LEAVE; SPAGAIN; RETURN; @@ -2843,7 +2865,7 @@ PP(pp_splice) else offset -= PL_curcop->cop_arybase; if (offset < 0) - DIE(PL_no_aelem, i); + DIE(aTHX_ PL_no_aelem, i); if (++MARK < SP) { length = SvIVx(*MARK++); if (length < 0) { @@ -3022,7 +3044,7 @@ PP(pp_push) PUSHMARK(MARK); PUTBACK; ENTER; - perl_call_method("PUSH",G_SCALAR|G_DISCARD); + call_method("PUSH",G_SCALAR|G_DISCARD); LEAVE; SPAGAIN; } @@ -3078,7 +3100,7 @@ PP(pp_unshift) PUSHMARK(MARK); PUTBACK; ENTER; - perl_call_method("UNSHIFT",G_SCALAR|G_DISCARD); + call_method("UNSHIFT",G_SCALAR|G_DISCARD); LEAVE; SPAGAIN; } @@ -3136,7 +3158,9 @@ PP(pp_reverse) s += UTF8SKIP(s); down = (char*)(s - 1); if (s > send || !((*down & 0xc0) == 0x80)) { - warn("Malformed UTF-8 character"); + if (ckWARN_d(WARN_UTF8)) + Perl_warner(aTHX_ WARN_UTF8, + "Malformed UTF-8 character"); break; } while (down > up) { @@ -3162,8 +3186,8 @@ PP(pp_reverse) RETURN; } -STATIC SV * -mul128(SV *sv, U8 m) +STATIC SV * +S_mul128(pTHX_ SV *sv, U8 m) { STRLEN len; char *s = SvPV(sv, len); @@ -3238,7 +3262,7 @@ PP(pp_unpack) double adouble; I32 checksum = 0; register U32 culong; - double cdouble; + NV cdouble; int commas = 0; #ifdef PERL_NATINT_PACK int natint; /* native integer */ @@ -3264,6 +3288,11 @@ PP(pp_unpack) #endif if (isSPACE(datumtype)) continue; + if (datumtype == '#') { + while (pat < patend && *pat != '\n') + pat++; + continue; + } if (*pat == '!') { char *natstr = "sSiIlL"; @@ -3274,7 +3303,7 @@ PP(pp_unpack) pat++; } else - croak("'!' allowed only after types %s", natstr); + Perl_croak(aTHX_ "'!' allowed only after types %s", natstr); } if (pat >= patend) len = 1; @@ -3284,17 +3313,20 @@ PP(pp_unpack) } else if (isDIGIT(*pat)) { len = *pat++ - '0'; - while (isDIGIT(*pat)) + while (isDIGIT(*pat)) { len = (len * 10) + (*pat++ - '0'); + if (len < 0) + Perl_croak(aTHX_ "Repeat count in unpack overflows"); + } } else len = (datumtype != '@'); switch(datumtype) { default: - croak("Invalid type in unpack: '%c'", (int)datumtype); + Perl_croak(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype); case ',': /* grandfather in commas but with a warning */ if (commas++ == 0 && ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE, "Invalid type in unpack: '%c'", (int)datumtype); + Perl_warner(aTHX_ WARN_UNSAFE, "Invalid type in unpack: '%c'", (int)datumtype); break; case '%': if (len == 1 && pat[-1] != '1') @@ -3307,19 +3339,31 @@ PP(pp_unpack) break; case '@': if (len > strend - strbeg) - DIE("@ outside of string"); + DIE(aTHX_ "@ outside of string"); s = strbeg + len; break; case 'X': if (len > s - strbeg) - DIE("X outside of string"); + DIE(aTHX_ "X outside of string"); s -= len; break; case 'x': if (len > strend - s) - DIE("x outside of string"); + DIE(aTHX_ "x outside of string"); s += len; break; + case '/': + if (oldsp >= SP) + DIE(aTHX_ "/ must follow a numeric type"); + if (*pat != 'a' && *pat != 'A' && *pat != 'Z') + DIE(aTHX_ "/ must be followed by a, A or Z"); + datumtype = *pat++; + if (*pat == '*') + pat++; /* ignore '*' for compatibility with pack */ + if (isDIGIT(*pat)) + DIE(aTHX_ "/ cannot take a count" ); + len = POPi; + /* drop through */ case 'A': case 'Z': case 'a': @@ -3502,7 +3546,7 @@ PP(pp_unpack) auint = utf8_to_uv((U8*)s, &along); s += along; if (checksum > 32) - cdouble += (double)auint; + cdouble += (NV)auint; else culong += auint; } @@ -3530,6 +3574,7 @@ PP(pp_unpack) if (checksum) { #if SHORTSIZE != SIZE16 if (natint) { + short ashort; while (len-- > 0) { COPYNN(s, &ashort, sizeof(short)); s += sizeof(short); @@ -3556,6 +3601,7 @@ PP(pp_unpack) EXTEND_MORTAL(len); #if SHORTSIZE != SIZE16 if (natint) { + short ashort; while (len-- > 0) { COPYNN(s, &ashort, sizeof(short)); s += sizeof(short); @@ -3595,6 +3641,7 @@ PP(pp_unpack) if (checksum) { #if SHORTSIZE != SIZE16 if (unatint) { + unsigned short aushort; while (len-- > 0) { COPYNN(s, &aushort, sizeof(unsigned short)); s += sizeof(unsigned short); @@ -3624,6 +3671,7 @@ PP(pp_unpack) EXTEND_MORTAL(len); #if SHORTSIZE != SIZE16 if (unatint) { + unsigned short aushort; while (len-- > 0) { COPYNN(s, &aushort, sizeof(unsigned short)); s += sizeof(unsigned short); @@ -3662,7 +3710,7 @@ PP(pp_unpack) Copy(s, &aint, 1, int); s += sizeof(int); if (checksum > 32) - cdouble += (double)aint; + cdouble += (NV)aint; else culong += aint; } @@ -3677,7 +3725,25 @@ PP(pp_unpack) #ifdef __osf__ /* Without the dummy below unpack("i", pack("i",-1)) * return 0xFFffFFff instead of -1 for Digital Unix V4.0 - * cc with optimization turned on */ + * cc with optimization turned on. + * + * The bug was detected in + * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (V4.0E) + * with optimization (-O4) turned on. + * DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (V4.0B) + * does not have this problem even with -O4. + * + * This bug was reported as DECC_BUGS 1431 + * and tracked internally as GEM_BUGS 7775. + * + * The bug is fixed in + * Tru64 UNIX V5.0: Compaq C V6.1-006 or later + * UNIX V4.0F support: DEC C V5.9-006 or later + * UNIX V4.0E support: DEC C V5.8-011 or later + * and also in DTK. + * + * See also few lines later for the same bug. + */ (aint) ? sv_setiv(sv, (IV)aint) : #endif @@ -3695,7 +3761,7 @@ PP(pp_unpack) Copy(s, &auint, 1, unsigned int); s += sizeof(unsigned int); if (checksum > 32) - cdouble += (double)auint; + cdouble += (NV)auint; else culong += auint; } @@ -3709,12 +3775,8 @@ PP(pp_unpack) sv = NEWSV(41, 0); #ifdef __osf__ /* Without the dummy below unpack("I", pack("I",0xFFFFFFFF)) - * returns 1.84467440737096e+19 instead of 0xFFFFFFFF for - * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (aka V4.0D) - * with optimization turned on. - * (DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (aka V4.0B) - * does not have this problem even with -O4) - */ + * returns 1.84467440737096e+19 instead of 0xFFFFFFFF. + * See details few lines earlier. */ (auint) ? sv_setuv(sv, (UV)auint) : #endif @@ -3734,11 +3796,12 @@ PP(pp_unpack) if (checksum) { #if LONGSIZE != SIZE32 if (natint) { + long along; while (len-- > 0) { COPYNN(s, &along, sizeof(long)); s += sizeof(long); if (checksum > 32) - cdouble += (double)along; + cdouble += (NV)along; else culong += along; } @@ -3754,7 +3817,7 @@ PP(pp_unpack) #endif s += SIZE32; if (checksum > 32) - cdouble += (double)along; + cdouble += (NV)along; else culong += along; } @@ -3765,6 +3828,7 @@ PP(pp_unpack) EXTEND_MORTAL(len); #if LONGSIZE != SIZE32 if (natint) { + long along; while (len-- > 0) { COPYNN(s, &along, sizeof(long)); s += sizeof(long); @@ -3804,11 +3868,12 @@ PP(pp_unpack) if (checksum) { #if LONGSIZE != SIZE32 if (unatint) { + unsigned long aulong; while (len-- > 0) { COPYNN(s, &aulong, sizeof(unsigned long)); s += sizeof(unsigned long); if (checksum > 32) - cdouble += (double)aulong; + cdouble += (NV)aulong; else culong += aulong; } @@ -3828,7 +3893,7 @@ PP(pp_unpack) aulong = vtohl(aulong); #endif if (checksum > 32) - cdouble += (double)aulong; + cdouble += (NV)aulong; else culong += aulong; } @@ -3839,6 +3904,7 @@ PP(pp_unpack) EXTEND_MORTAL(len); #if LONGSIZE != SIZE32 if (unatint) { + unsigned long aulong; while (len-- > 0) { COPYNN(s, &aulong, sizeof(unsigned long)); s += sizeof(unsigned long); @@ -3908,7 +3974,7 @@ PP(pp_unpack) char *t; STRLEN n_a; - sv = newSVpvf("%.*Vu", (int)TYPE_DIGITS(UV), auv); + sv = Perl_newSVpvf(aTHX_ "%.*Vu", (int)TYPE_DIGITS(UV), auv); while (s < strend) { sv = mul128(sv, *s & 0x7f); if (!(*s++ & 0x80)) { @@ -3926,7 +3992,7 @@ PP(pp_unpack) } } if ((s >= strend) && bytes) - croak("Unterminated compressed integer"); + Perl_croak(aTHX_ "Unterminated compressed integer"); } break; case 'P': @@ -3960,7 +4026,7 @@ PP(pp_unpack) if (aquad >= IV_MIN && aquad <= IV_MAX) sv_setiv(sv, (IV)aquad); else - sv_setnv(sv, (double)aquad); + sv_setnv(sv, (NV)aquad); PUSHs(sv_2mortal(sv)); } break; @@ -3981,7 +4047,7 @@ PP(pp_unpack) if (auquad <= UV_MAX) sv_setuv(sv, (UV)auquad); else - sv_setnv(sv, (double)auquad); + sv_setnv(sv, (NV)auquad); PUSHs(sv_2mortal(sv)); } break; @@ -4006,7 +4072,7 @@ PP(pp_unpack) Copy(s, &afloat, 1, float); s += sizeof(float); sv = NEWSV(47, 0); - sv_setnv(sv, (double)afloat); + sv_setnv(sv, (NV)afloat); PUSHs(sv_2mortal(sv)); } } @@ -4030,7 +4096,7 @@ PP(pp_unpack) Copy(s, &adouble, 1, double); s += sizeof(double); sv = NEWSV(48, 0); - sv_setnv(sv, (double)adouble); + sv_setnv(sv, (NV)adouble); PUSHs(sv_2mortal(sv)); } } @@ -4098,7 +4164,7 @@ PP(pp_unpack) sv = NEWSV(42, 0); if (strchr("fFdD", datumtype) || (checksum > 32 && strchr("iIlLNU", datumtype)) ) { - double trouble; + NV trouble; adouble = 1.0; while (checksum >= 16) { @@ -4114,7 +4180,7 @@ PP(pp_unpack) along = (1 << checksum) - 1; while (cdouble < 0.0) cdouble += adouble; - cdouble = modf(cdouble / adouble, &trouble) * adouble; + cdouble = Perl_modf(cdouble / adouble, &trouble) * adouble; sv_setnv(sv, cdouble); } else { @@ -4134,7 +4200,7 @@ PP(pp_unpack) } STATIC void -doencodes(register SV *sv, register char *s, register I32 len) +S_doencodes(pTHX_ register SV *sv, register char *s, register I32 len) { char hunk[5]; @@ -4162,7 +4228,7 @@ doencodes(register SV *sv, register char *s, register I32 len) } STATIC SV * -is_an_int(char *s, STRLEN l) +S_is_an_int(pTHX_ char *s, STRLEN l) { STRLEN n_a; SV *result = newSVpvn(s, l); @@ -4210,10 +4276,9 @@ is_an_int(char *s, STRLEN l) return (result); } +/* pnum must be '\0' terminated */ STATIC int -div128(SV *pnum, bool *done) - /* must be '\0' terminated */ - +S_div128(pTHX_ SV *pnum, bool *done) { STRLEN len; char *s = SvPV(pnum, len); @@ -4277,13 +4342,19 @@ PP(pp_pack) MARK++; sv_setpvn(cat, "", 0); while (pat < patend) { -#define NEXTFROM (items-- > 0 ? *MARK++ : &PL_sv_no) + SV *lengthcode = Nullsv; +#define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *MARK++ : &PL_sv_no) datumtype = *pat++ & 0xFF; #ifdef PERL_NATINT_PACK natint = 0; #endif if (isSPACE(datumtype)) continue; + if (datumtype == '#') { + while (pat < patend && *pat != '\n') + pat++; + continue; + } if (*pat == '!') { char *natstr = "sSiIlL"; @@ -4294,7 +4365,7 @@ PP(pp_pack) pat++; } else - croak("'!' allowed only after types %s", natstr); + Perl_croak(aTHX_ "'!' allowed only after types %s", natstr); } if (*pat == '*') { len = strchr("@Xxu", datumtype) ? 0 : items; @@ -4302,20 +4373,31 @@ PP(pp_pack) } else if (isDIGIT(*pat)) { len = *pat++ - '0'; - while (isDIGIT(*pat)) + while (isDIGIT(*pat)) { len = (len * 10) + (*pat++ - '0'); + if (len < 0) + Perl_croak(aTHX_ "Repeat count in pack overflows"); + } } else len = 1; + if (*pat == '/') { + ++pat; + if (*pat != 'a' && *pat != 'A' && *pat != 'Z' || pat[1] != '*') + DIE(aTHX_ "/ must be followed by a*, A* or Z*"); + lengthcode = sv_2mortal(newSViv(sv_len(items > 0 + ? *MARK : &PL_sv_no))); + } switch(datumtype) { default: - croak("Invalid type in pack: '%c'", (int)datumtype); + Perl_croak(aTHX_ "Invalid type in pack: '%c'", (int)datumtype); case ',': /* grandfather in commas but with a warning */ if (commas++ == 0 && ckWARN(WARN_UNSAFE)) - warner(WARN_UNSAFE, "Invalid type in pack: '%c'", (int)datumtype); + Perl_warner(aTHX_ WARN_UNSAFE, + "Invalid type in pack: '%c'", (int)datumtype); break; case '%': - DIE("%% may only be used in unpack"); + DIE(aTHX_ "%% may only be used in unpack"); case '@': len -= SvCUR(cat); if (len > 0) @@ -4327,7 +4409,7 @@ PP(pp_pack) case 'X': shrink: if (SvCUR(cat) < len) - DIE("X outside of string"); + DIE(aTHX_ "X outside of string"); SvCUR(cat) -= len; *SvEND(cat) = '\0'; break; @@ -4566,6 +4648,8 @@ PP(pp_pack) case 's': #if SHORTSIZE != SIZE16 if (natint) { + short ashort; + while (len-- > 0) { fromstr = NEXTFROM; ashort = SvIV(fromstr); @@ -4592,10 +4676,10 @@ PP(pp_pack) case 'w': while (len-- > 0) { fromstr = NEXTFROM; - adouble = floor(SvNV(fromstr)); + adouble = Perl_floor(SvNV(fromstr)); if (adouble < 0) - croak("Cannot compress negative numbers"); + Perl_croak(aTHX_ "Cannot compress negative numbers"); if ( #ifdef BW_BITS @@ -4611,7 +4695,7 @@ PP(pp_pack) { char buf[1 + sizeof(UV)]; char *in = buf + sizeof(buf); - UV auv = U_V(adouble);; + UV auv = U_V(adouble); do { *--in = (auv & 0x7f) | 0x80; @@ -4629,7 +4713,7 @@ PP(pp_pack) /* Copy string and check for compliance */ from = SvPV(fromstr, len); if ((norm = is_an_int(from, len)) == NULL) - croak("can compress only unsigned integer"); + Perl_croak(aTHX_ "can compress only unsigned integer"); New('w', result, len, char); in = result + len; @@ -4649,14 +4733,14 @@ PP(pp_pack) double next = floor(adouble / 128); *--in = (unsigned char)(adouble - (next * 128)) | 0x80; if (--in < buf) /* this cannot happen ;-) */ - croak ("Cannot compress integer"); + Perl_croak(aTHX_ "Cannot compress integer"); adouble = next; } while (adouble > 0); buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */ sv_catpvn(cat, in, (buf + sizeof(buf)) - in); } else - croak("Cannot compress non integer"); + Perl_croak(aTHX_ "Cannot compress non integer"); } break; case 'i': @@ -4689,6 +4773,8 @@ PP(pp_pack) case 'L': #if LONGSIZE != SIZE32 if (natint) { + unsigned long aulong; + while (len-- > 0) { fromstr = NEXTFROM; aulong = SvUV(fromstr); @@ -4708,6 +4794,8 @@ PP(pp_pack) case 'l': #if LONGSIZE != SIZE32 if (natint) { + long along; + while (len-- > 0) { fromstr = NEXTFROM; along = SvIV(fromstr); @@ -4728,7 +4816,7 @@ PP(pp_pack) case 'Q': while (len-- > 0) { fromstr = NEXTFROM; - auquad = (Uquad_t)SvIV(fromstr); + auquad = (Uquad_t)SvUV(fromstr); sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t)); } break; @@ -4756,7 +4844,7 @@ PP(pp_pack) * gone. */ if (ckWARN(WARN_UNSAFE) && (SvTEMP(fromstr) || SvPADTMP(fromstr))) - warner(WARN_UNSAFE, + Perl_warner(aTHX_ WARN_UNSAFE, "Attempt to pack pointer to temporary value"); if (SvPOK(fromstr) || SvNIOK(fromstr)) aptr = SvPV(fromstr,n_a); @@ -4828,7 +4916,7 @@ PP(pp_split) pm = (PMOP*)POPs; #endif if (!pm || !s) - DIE("panic: do_split"); + DIE(aTHX_ "panic: do_split"); rx = pm->op_pmregexp; TAINT_IF((pm->op_pmflags & PMf_LOCALE) && @@ -4857,6 +4945,7 @@ PP(pp_split) else { if (!AvREAL(ary)) { AvREAL_on(ary); + AvREIFY_off(ary); for (i = AvFILLp(ary); i >= 0; i--) AvARRAY(ary)[i] = &PL_sv_undef; /* don't free mere refs */ } @@ -4922,15 +5011,19 @@ PP(pp_split) s = m; } } - else if (rx->check_substr && !rx->nparens + else if ((rx->reganch & RE_USE_INTUIT) && !rx->nparens && (rx->reganch & ROPT_CHECK_ALL) && !(rx->reganch & ROPT_ANCH)) { - i = SvCUR(rx->check_substr); - if (i == 1 && !SvTAIL(rx->check_substr)) { - i = *SvPVX(rx->check_substr); + int tail = (rx->reganch & RE_INTUIT_TAIL); + SV *csv = CALLREG_INTUIT_STRING(aTHX_ rx); + char c; + + len = rx->minlen; + if (len == 1 && !tail) { + c = *SvPV(csv,len); while (--limit) { /*SUPPRESS 530*/ - for (m = s; m < strend && *m != i; m++) ; + for (m = s; m < strend && *m != c; m++) ; if (m >= strend) break; dstr = NEWSV(30, m-s); @@ -4944,8 +5037,8 @@ PP(pp_split) else { #ifndef lint while (s < strend && --limit && - (m=fbm_instr((unsigned char*)s, (unsigned char*)strend, - rx->check_substr, 0)) ) + (m = fbm_instr((unsigned char*)s, (unsigned char*)strend, + csv, PL_multiline ? FBMrf_MULTILINE : 0)) ) #endif { dstr = NEWSV(31, m-s); @@ -4953,25 +5046,28 @@ PP(pp_split) if (make_mortal) sv_2mortal(dstr); XPUSHs(dstr); - s = m + i; + s = m + len; /* Fake \n at the end */ } } } else { maxiters += (strend - s) * rx->nparens; - while (s < strend && --limit && - CALLREGEXEC(rx, s, strend, orig, 1, sv, NULL, 0)) + while (s < strend && --limit +/* && (!rx->check_substr + || ((s = CALLREG_INTUIT_START(aTHX_ rx, sv, s, strend, + 0, NULL)))) +*/ && CALLREGEXEC(aTHX_ rx, s, strend, orig, + 1 /* minend */, sv, NULL, 0)) { TAINT_IF(RX_MATCH_TAINTED(rx)); - if (rx->subbase - && rx->subbase != orig) { + if (RX_MATCH_COPIED(rx) && rx->subbeg != orig) { m = s; s = orig; - orig = rx->subbase; + orig = rx->subbeg; s = orig + (m - s); strend = s + (strend - m); } - m = rx->startp[0]; + m = rx->startp[0] + orig; dstr = NEWSV(32, m-s); sv_setpvn(dstr, s, m-s); if (make_mortal) @@ -4979,8 +5075,8 @@ PP(pp_split) XPUSHs(dstr); if (rx->nparens) { for (i = 1; i <= rx->nparens; i++) { - s = rx->startp[i]; - m = rx->endp[i]; + s = rx->startp[i] + orig; + m = rx->endp[i] + orig; if (m && s) { dstr = NEWSV(33, m-s); sv_setpvn(dstr, s, m-s); @@ -4992,14 +5088,14 @@ PP(pp_split) XPUSHs(dstr); } } - s = rx->endp[0]; + s = rx->endp[0] + orig; } } LEAVE_SCOPE(oldsave); iters = (SP - PL_stack_base) - base; if (iters > maxiters) - DIE("Split loop"); + DIE(aTHX_ "Split loop"); /* keep field after final delim? */ if (s < strend || (iters && origlimit)) { @@ -5033,7 +5129,7 @@ PP(pp_split) else { PUTBACK; ENTER; - perl_call_method("PUSH",G_SCALAR|G_DISCARD); + call_method("PUSH",G_SCALAR|G_DISCARD); LEAVE; SPAGAIN; if (gimme == G_ARRAY) { @@ -5061,16 +5157,16 @@ PP(pp_split) #ifdef USE_THREADS void -unlock_condpair(void *svv) +Perl_unlock_condpair(pTHX_ void *svv) { dTHR; MAGIC *mg = mg_find((SV*)svv, 'm'); if (!mg) - croak("panic: unlock_condpair unlocking non-mutex"); + Perl_croak(aTHX_ "panic: unlock_condpair unlocking non-mutex"); MUTEX_LOCK(MgMUTEXP(mg)); if (MgOWNER(mg) != thr) - croak("panic: unlock_condpair unlocking mutex that we don't own"); + Perl_croak(aTHX_ "panic: unlock_condpair unlocking mutex that we don't own"); MgOWNER(mg) = 0; COND_SIGNAL(MgOWNERCONDP(mg)); DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: unlock 0x%lx\n", @@ -5101,7 +5197,7 @@ PP(pp_lock) DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n", (unsigned long)thr, (unsigned long)sv);) MUTEX_UNLOCK(MgMUTEXP(mg)); - save_destructor(unlock_condpair, sv); + SAVEDESTRUCTOR(Perl_unlock_condpair, sv); } #endif /* USE_THREADS */ if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV @@ -5123,6 +5219,6 @@ PP(pp_threadsv) PUSHs(THREADSV(PL_op->op_targ)); RETURN; #else - DIE("tried to access per-thread data in non-threaded perl"); + DIE(aTHX_ "tried to access per-thread data in non-threaded perl"); #endif /* USE_THREADS */ }