X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_ctl.c;h=fd1bccd6d89a824119f872f993b0b4b21fa0465c;hb=bddd5118bb8dac8628019bdb9373c01f5937db98;hp=bb576d5e39ef97932014885bd9c84590564a5a02;hpb=ed8d0fe2473523a42189f0c3b912e68bf4ca9b1b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_ctl.c b/pp_ctl.c index bb576d5..fd1bccd 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1,6 +1,7 @@ /* pp_ctl.c * - * Copyright (c) 1991-2002, Larry Wall + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + * 2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -16,12 +17,23 @@ * And whither then? I cannot say. */ +/* This file contains control-oriented pp ("push/pop") functions that + * execute the opcodes that make up a perl program. A typical pp function + * expects to find its arguments on the stack, and usually pushes its + * results onto the stack, hence the 'pp' terminology. Each OP structure + * contains a pointer to the relevant pp_foo() function. + * + * Control-oriented means things like pp_enteriter() and pp_next(), which + * alter the flow of control of the program. + */ + + #include "EXTERN.h" #define PERL_IN_PP_CTL_C #include "perl.h" #ifndef WORD_ALIGN -#define WORD_ALIGN sizeof(U16) +#define WORD_ALIGN sizeof(U32) #endif #define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o)) @@ -58,6 +70,7 @@ PP(pp_regcreset) /* XXXX Should store the old value to allow for tie/overload - and restore in regcomp, where marked with XXXX. */ PL_reginterp_cnt = 0; + TAINT_NOT; return NORMAL; } @@ -65,18 +78,43 @@ PP(pp_regcomp) { dSP; register PMOP *pm = (PMOP*)cLOGOP->op_other; - register char *t; SV *tmpstr; - STRLEN len; MAGIC *mg = Null(MAGIC*); - - tmpstr = POPs; /* prevent recompiling under /o and ithreads. */ #if defined(USE_ITHREADS) - if (pm->op_pmflags & PMf_KEEP && PM_GETRE(pm)) - RETURN; + if (pm->op_pmflags & PMf_KEEP && PM_GETRE(pm)) { + if (PL_op->op_flags & OPf_STACKED) { + dMARK; + SP = MARK; + } + else + (void)POPs; + RETURN; + } #endif + if (PL_op->op_flags & OPf_STACKED) { + /* multiple args; concatentate them */ + dMARK; dORIGMARK; + tmpstr = PAD_SV(ARGTARG); + sv_setpvn(tmpstr, "", 0); + while (++MARK <= SP) { + if (PL_amagic_generation) { + SV *sv; + if ((SvAMAGIC(tmpstr) || SvAMAGIC(*MARK)) && + (sv = amagic_call(tmpstr, *MARK, concat_amg, AMGf_assign))) + { + sv_setsv(tmpstr, sv); + continue; + } + } + sv_catsv(tmpstr, *MARK); + } + SvSETMAGIC(tmpstr); + SP = ORIGMARK; + } + else + tmpstr = POPs; if (SvROK(tmpstr)) { SV *sv = SvRV(tmpstr); @@ -84,12 +122,13 @@ PP(pp_regcomp) mg = mg_find(sv, PERL_MAGIC_qr); } if (mg) { - regexp *re = (regexp *)mg->mg_obj; + regexp * const re = (regexp *)mg->mg_obj; ReREFCNT_dec(PM_GETRE(pm)); PM_SETRE(pm, ReREFCNT_inc(re)); } else { - t = SvPV(tmpstr, len); + STRLEN len; + const char *t = SvPV_const(tmpstr, len); /* Check against the last compiled regexp. */ if (!PM_GETRE(pm) || !PM_GETRE(pm)->precomp || @@ -97,7 +136,7 @@ PP(pp_regcomp) memNE(PM_GETRE(pm)->precomp, t, len)) { if (PM_GETRE(pm)) { - ReREFCNT_dec(PM_GETRE(pm)); + ReREFCNT_dec(PM_GETRE(pm)); PM_SETRE(pm, Null(REGEXP*)); /* crucial if regcomp aborts */ } if (PL_op->op_flags & OPf_SPECIAL) @@ -111,7 +150,7 @@ PP(pp_regcomp) if (pm->op_pmdynflags & PMdf_UTF8) t = (char*)bytes_to_utf8((U8*)t, &len); } - PM_SETRE(pm, CALLREGCOMP(aTHX_ t, t + len, pm)); + PM_SETRE(pm, CALLREGCOMP(aTHX_ (char *)t, (char *)t + len, pm)); if (!DO_UTF8(tmpstr) && (pm->op_pmdynflags & PMdf_UTF8)) Safefree(t); PL_reginterp_cnt = 0; /* XXXX Be extra paranoid - needed @@ -149,19 +188,26 @@ PP(pp_regcomp) PP(pp_substcont) { dSP; - register PMOP *pm = (PMOP*) cLOGOP->op_other; register PERL_CONTEXT *cx = &cxstack[cxstack_ix]; - register SV *dstr = cx->sb_dstr; + register PMOP * const pm = (PMOP*) cLOGOP->op_other; + register SV * const dstr = cx->sb_dstr; register char *s = cx->sb_s; register char *m = cx->sb_m; char *orig = cx->sb_orig; - register REGEXP *rx = cx->sb_rx; + register REGEXP * const rx = cx->sb_rx; + SV *nsv = Nullsv; + REGEXP *old = PM_GETRE(pm); + if(old != rx) { + if(old) + ReREFCNT_dec(old); + PM_SETRE(pm,rx); + } rxres_restore(&cx->sb_rxres, rx); - PL_reg_match_utf8 = SvUTF8(cx->sb_targ) ? 1 : 0; + RX_MATCH_UTF8_set(rx, DO_UTF8(cx->sb_targ)); if (cx->sb_iters++) { - I32 saviters = cx->sb_iters; + const I32 saviters = cx->sb_iters; if (cx->sb_iters > cx->sb_maxiters) DIE(aTHX_ "Substitution loop"); @@ -176,23 +222,35 @@ PP(pp_substcont) ? (REXEC_IGNOREPOS|REXEC_NOT_FIRST) : (REXEC_COPY_STR|REXEC_IGNOREPOS|REXEC_NOT_FIRST)))) { - SV *targ = cx->sb_targ; + SV * const targ = cx->sb_targ; - sv_catpvn(dstr, s, cx->sb_strend - s); + assert(cx->sb_strend >= s); + if(cx->sb_strend > s) { + if (DO_UTF8(dstr) && !SvUTF8(targ)) + sv_catpvn_utf8_upgrade(dstr, s, cx->sb_strend - s, nsv); + else + sv_catpvn(dstr, s, cx->sb_strend - s); + } cx->sb_rxtainted |= RX_MATCH_TAINTED(rx); - (void)SvOOK_off(targ); - Safefree(SvPVX(targ)); - SvPVX(targ) = SvPVX(dstr); +#ifdef PERL_OLD_COPY_ON_WRITE + if (SvIsCOW(targ)) { + sv_force_normal_flags(targ, SV_COW_DROP_PV); + } else +#endif + { + SvPV_free(targ); + } + SvPV_set(targ, SvPVX(dstr)); SvCUR_set(targ, SvCUR(dstr)); SvLEN_set(targ, SvLEN(dstr)); if (DO_UTF8(dstr)) SvUTF8_on(targ); - SvPVX(dstr) = 0; + SvPV_set(dstr, (char*)0); sv_free(dstr); TAINT_IF(cx->sb_rxtainted & 1); - PUSHs(sv_2mortal(newSViv((I32)cx->sb_iters - 1))); + PUSHs(sv_2mortal(newSViv(saviters - 1))); (void)SvPOK_only_UTF8(targ); TAINT_IF(cx->sb_rxtainted); @@ -200,6 +258,7 @@ PP(pp_substcont) SvTAINT(targ); LEAVE_SCOPE(cx->sb_oldsave); + ReREFCNT_dec(rx); POPSUBST(cx); RETURNOP(pm->op_next); } @@ -213,15 +272,19 @@ PP(pp_substcont) cx->sb_strend = s + (cx->sb_strend - m); } cx->sb_m = m = rx->startp[0] + orig; - if (m > s) - sv_catpvn(dstr, s, m-s); + if (m > s) { + if (DO_UTF8(dstr) && !SvUTF8(cx->sb_targ)) + sv_catpvn_utf8_upgrade(dstr, s, m - s, nsv); + else + sv_catpvn(dstr, s, m-s); + } cx->sb_s = rx->endp[0] + orig; { /* Update the pos() information. */ - SV *sv = cx->sb_targ; + SV * const sv = cx->sb_targ; MAGIC *mg; I32 i; if (SvTYPE(sv) < SVt_PVMG) - (void)SvUPGRADE(sv, SVt_PVMG); + SvUPGRADE(sv, SVt_PVMG); if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) { sv_magic(sv, Nullsv, PERL_MAGIC_regex_global, Nullch, 0); mg = mg_find(sv, PERL_MAGIC_regex_global); @@ -231,6 +294,8 @@ PP(pp_substcont) sv_pos_b2u(sv, &i); mg->mg_len = i; } + if (old != rx) + (void)ReREFCNT_inc(rx); cx->sb_rxtainted |= RX_MATCH_TAINTED(rx); rxres_save(&cx->sb_rxres, rx); RETURNOP(pm->op_pmreplstart); @@ -243,9 +308,13 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) U32 i; if (!p || p[1] < rx->nparens) { +#ifdef PERL_OLD_COPY_ON_WRITE + i = 7 + rx->nparens * 2; +#else i = 6 + rx->nparens * 2; +#endif if (!p) - New(501, p, i, UV); + Newx(p, i, UV); else Renew(p, i, UV); *rsp = (void*)p; @@ -254,6 +323,11 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) *p++ = PTR2UV(RX_MATCH_COPIED(rx) ? rx->subbeg : Nullch); RX_MATCH_COPIED_off(rx); +#ifdef PERL_OLD_COPY_ON_WRITE + *p++ = PTR2UV(rx->saved_copy); + rx->saved_copy = Nullsv; +#endif + *p++ = rx->nparens; *p++ = PTR2UV(rx->subbeg); @@ -270,11 +344,17 @@ Perl_rxres_restore(pTHX_ void **rsp, REGEXP *rx) UV *p = (UV*)*rsp; U32 i; - if (RX_MATCH_COPIED(rx)) - Safefree(rx->subbeg); + RX_MATCH_COPY_FREE(rx); RX_MATCH_COPIED_set(rx, *p); *p++ = 0; +#ifdef PERL_OLD_COPY_ON_WRITE + if (rx->saved_copy) + SvREFCNT_dec (rx->saved_copy); + rx->saved_copy = INT2PTR(SV*,*p); + *p++ = 0; +#endif + rx->nparens = *p++; rx->subbeg = INT2PTR(char*,*p++); @@ -288,10 +368,22 @@ Perl_rxres_restore(pTHX_ void **rsp, REGEXP *rx) void Perl_rxres_free(pTHX_ void **rsp) { - UV *p = (UV*)*rsp; + UV * const p = (UV*)*rsp; if (p) { +#ifdef PERL_POISON + void *tmp = INT2PTR(char*,*p); + Safefree(tmp); + if (*p) + Poison(*p, 1, sizeof(*p)); +#else Safefree(INT2PTR(char*,*p)); +#endif +#ifdef PERL_OLD_COPY_ON_WRITE + if (p[1]) { + SvREFCNT_dec (INT2PTR(SV*,p[1])); + } +#endif Safefree(p); *rsp = Null(void*); } @@ -300,49 +392,54 @@ Perl_rxres_free(pTHX_ void **rsp) PP(pp_formline) { dSP; dMARK; dORIGMARK; - register SV *tmpForm = *++MARK; - register U16 *fpc; + register SV * const tmpForm = *++MARK; + register U32 *fpc; register char *t; - register char *f; - register char *s; - register char *send; + const char *f; register I32 arg; register SV *sv = Nullsv; - char *item = Nullch; + const char *item = Nullch; I32 itemsize = 0; I32 fieldsize = 0; I32 lines = 0; bool chopspace = (strchr(PL_chopset, ' ') != Nullch); - char *chophere = Nullch; + const char *chophere = Nullch; char *linemark = Nullch; NV value; bool gotsome = FALSE; STRLEN len; - STRLEN fudge = SvCUR(tmpForm) * (IN_BYTES ? 1 : 3) + 1; - bool item_is_utf = FALSE; + const STRLEN fudge = SvPOK(tmpForm) + ? (SvCUR(tmpForm) * (IN_BYTES ? 1 : 3) + 1) : 0; + bool item_is_utf8 = FALSE; + bool targ_is_utf8 = FALSE; + SV * nsv = Nullsv; + OP * parseres = 0; + const char *fmt; + bool oneline; if (!SvMAGICAL(tmpForm) || !SvCOMPILED(tmpForm)) { if (SvREADONLY(tmpForm)) { SvREADONLY_off(tmpForm); - doparseform(tmpForm); + parseres = doparseform(tmpForm); SvREADONLY_on(tmpForm); } else - doparseform(tmpForm); + parseres = doparseform(tmpForm); + if (parseres) + return parseres; } - SvPV_force(PL_formtarget, len); + if (DO_UTF8(PL_formtarget)) + targ_is_utf8 = TRUE; t = SvGROW(PL_formtarget, len + fudge + 1); /* XXX SvCUR bad */ t += len; - f = SvPV(tmpForm, len); + f = SvPV_const(tmpForm, len); /* need to jump to the next word */ - s = f + len + WORD_ALIGN - SvCUR(tmpForm) % WORD_ALIGN; - - fpc = (U16*)s; + fpc = (U32*)(f + len + WORD_ALIGN - SvCUR(tmpForm) % WORD_ALIGN); for (;;) { DEBUG_f( { - char *name = "???"; + const char *name = "???"; arg = -1; switch (*fpc) { case FF_LITERAL: arg = fpc[1]; name = "LITERAL"; break; @@ -362,7 +459,8 @@ PP(pp_formline) case FF_MORE: name = "MORE"; break; case FF_LINEMARK: name = "LINEMARK"; break; case FF_END: name = "END"; break; - case FF_0DECIMAL: name = "0DECIMAL"; break; + case FF_0DECIMAL: name = "0DECIMAL"; break; + case FF_LINESNGL: name = "LINESNGL"; break; } if (arg >= 0) PerlIO_printf(Perl_debug_log, "%-16s%ld\n", name, (long) arg); @@ -378,6 +476,21 @@ PP(pp_formline) case FF_LITERAL: arg = *fpc++; + if (targ_is_utf8 && !SvUTF8(tmpForm)) { + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + *t = '\0'; + sv_catpvn_utf8_upgrade(PL_formtarget, f, arg, nsv); + t = SvEND(PL_formtarget); + break; + } + if (!targ_is_utf8 && DO_UTF8(tmpForm)) { + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + *t = '\0'; + sv_utf8_upgrade(PL_formtarget); + SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1); + t = SvEND(PL_formtarget); + targ_is_utf8 = TRUE; + } while (arg--) *t++ = *f++; break; @@ -401,125 +514,134 @@ PP(pp_formline) break; case FF_CHECKNL: - item = s = SvPV(sv, len); - itemsize = len; - if (DO_UTF8(sv)) { - itemsize = sv_len_utf8(sv); - if (itemsize != (I32)len) { - I32 itembytes; - if (itemsize > fieldsize) { - itemsize = fieldsize; - itembytes = itemsize; - sv_pos_u2b(sv, &itembytes, 0); - } - else - itembytes = len; - send = chophere = s + itembytes; - while (s < send) { - if (*s & ~31) - gotsome = TRUE; - else if (*s == '\n') - break; - s++; + { + const char *send; + const char *s = item = SvPV_const(sv, len); + itemsize = len; + if (DO_UTF8(sv)) { + itemsize = sv_len_utf8(sv); + if (itemsize != (I32)len) { + I32 itembytes; + if (itemsize > fieldsize) { + itemsize = fieldsize; + itembytes = itemsize; + sv_pos_u2b(sv, &itembytes, 0); + } + else + itembytes = len; + send = chophere = s + itembytes; + while (s < send) { + if (*s & ~31) + gotsome = TRUE; + else if (*s == '\n') + break; + s++; + } + item_is_utf8 = TRUE; + itemsize = s - item; + sv_pos_b2u(sv, &itemsize); + break; } - item_is_utf = TRUE; - itemsize = s - item; - sv_pos_b2u(sv, &itemsize); - break; } + item_is_utf8 = FALSE; + if (itemsize > fieldsize) + itemsize = fieldsize; + send = chophere = s + itemsize; + while (s < send) { + if (*s & ~31) + gotsome = TRUE; + else if (*s == '\n') + break; + s++; + } + itemsize = s - item; + break; } - item_is_utf = FALSE; - if (itemsize > fieldsize) - itemsize = fieldsize; - send = chophere = s + itemsize; - while (s < send) { - if (*s & ~31) - gotsome = TRUE; - else if (*s == '\n') - break; - s++; - } - itemsize = s - item; - break; case FF_CHECKCHOP: - item = s = SvPV(sv, len); - itemsize = len; - if (DO_UTF8(sv)) { - itemsize = sv_len_utf8(sv); - if (itemsize != (I32)len) { - I32 itembytes; - if (itemsize <= fieldsize) { - send = chophere = s + itemsize; - while (s < send) { - if (*s == '\r') { - itemsize = s - item; - break; - } - if (*s++ & ~31) - gotsome = TRUE; - } - } - else { - itemsize = fieldsize; - itembytes = itemsize; - sv_pos_u2b(sv, &itembytes, 0); - send = chophere = s + itembytes; - while (s < send || (s == send && isSPACE(*s))) { - if (isSPACE(*s)) { - if (chopspace) + { + const char *s = item = SvPV_const(sv, len); + itemsize = len; + if (DO_UTF8(sv)) { + itemsize = sv_len_utf8(sv); + if (itemsize != (I32)len) { + I32 itembytes; + if (itemsize <= fieldsize) { + const char *send = chophere = s + itemsize; + while (s < send) { + if (*s == '\r') { + itemsize = s - item; chophere = s; - if (*s == '\r') break; - } - else { - if (*s & ~31) + } + if (*s++ & ~31) gotsome = TRUE; - if (strchr(PL_chopset, *s)) - chophere = s + 1; } - s++; } - itemsize = chophere - item; - sv_pos_b2u(sv, &itemsize); - } - item_is_utf = TRUE; - break; - } - } - item_is_utf = FALSE; - if (itemsize <= fieldsize) { - send = chophere = s + itemsize; - while (s < send) { - if (*s == '\r') { - itemsize = s - item; + else { + const char *send; + itemsize = fieldsize; + itembytes = itemsize; + sv_pos_u2b(sv, &itembytes, 0); + send = chophere = s + itembytes; + while (s < send || (s == send && isSPACE(*s))) { + if (isSPACE(*s)) { + if (chopspace) + chophere = s; + if (*s == '\r') + break; + } + else { + if (*s & ~31) + gotsome = TRUE; + if (strchr(PL_chopset, *s)) + chophere = s + 1; + } + s++; + } + itemsize = chophere - item; + sv_pos_b2u(sv, &itemsize); + } + item_is_utf8 = TRUE; break; } - if (*s++ & ~31) - gotsome = TRUE; } - } - else { - itemsize = fieldsize; - send = chophere = s + itemsize; - while (s < send || (s == send && isSPACE(*s))) { - if (isSPACE(*s)) { - if (chopspace) + item_is_utf8 = FALSE; + if (itemsize <= fieldsize) { + const char *const send = chophere = s + itemsize; + while (s < send) { + if (*s == '\r') { + itemsize = s - item; chophere = s; - if (*s == '\r') break; - } - else { - if (*s & ~31) + } + if (*s++ & ~31) gotsome = TRUE; - if (strchr(PL_chopset, *s)) - chophere = s + 1; } - s++; } - itemsize = chophere - item; + else { + const char *send; + itemsize = fieldsize; + send = chophere = s + itemsize; + while (s < send || (s == send && isSPACE(*s))) { + if (isSPACE(*s)) { + if (chopspace) + chophere = s; + if (*s == '\r') + break; + } + else { + if (*s & ~31) + gotsome = TRUE; + if (strchr(PL_chopset, *s)) + chophere = s + 1; + } + s++; + } + itemsize = chophere - item; + } + break; } - break; case FF_SPACE: arg = fieldsize - itemsize; @@ -541,116 +663,151 @@ PP(pp_formline) break; case FF_ITEM: - arg = itemsize; - s = item; - if (item_is_utf) { - while (arg--) { - if (UTF8_IS_CONTINUED(*s)) { - STRLEN skip = UTF8SKIP(s); - switch (skip) { - default: - Move(s,t,skip,char); - s += skip; - t += skip; - break; - case 7: *t++ = *s++; - case 6: *t++ = *s++; - case 5: *t++ = *s++; - case 4: *t++ = *s++; - case 3: *t++ = *s++; - case 2: *t++ = *s++; - case 1: *t++ = *s++; + { + const char *s = item; + arg = itemsize; + if (item_is_utf8) { + if (!targ_is_utf8) { + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + *t = '\0'; + sv_utf8_upgrade(PL_formtarget); + SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1); + t = SvEND(PL_formtarget); + targ_is_utf8 = TRUE; + } + while (arg--) { + if (UTF8_IS_CONTINUED(*s)) { + STRLEN skip = UTF8SKIP(s); + switch (skip) { + default: + Move(s,t,skip,char); + s += skip; + t += skip; + break; + case 7: *t++ = *s++; + case 6: *t++ = *s++; + case 5: *t++ = *s++; + case 4: *t++ = *s++; + case 3: *t++ = *s++; + case 2: *t++ = *s++; + case 1: *t++ = *s++; + } + } + else { + if ( !((*t++ = *s++) & ~31) ) + t[-1] = ' '; } } - else { - if ( !((*t++ = *s++) & ~31) ) - t[-1] = ' '; + break; + } + if (targ_is_utf8 && !item_is_utf8) { + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + *t = '\0'; + sv_catpvn_utf8_upgrade(PL_formtarget, s, arg, nsv); + for (; t < SvEND(PL_formtarget); t++) { +#ifdef EBCDIC + const int ch = *t; + if (iscntrl(ch)) +#else + if (!(*t & ~31)) +#endif + *t = ' '; } + break; } - break; - } - while (arg--) { + while (arg--) { #ifdef EBCDIC - int ch = *t++ = *s++; - if (iscntrl(ch)) + const int ch = *t++ = *s++; + if (iscntrl(ch)) #else - if ( !((*t++ = *s++) & ~31) ) + if ( !((*t++ = *s++) & ~31) ) #endif - t[-1] = ' '; + t[-1] = ' '; + } + break; } - break; case FF_CHOP: - s = chophere; - if (chopspace) { - while (*s && isSPACE(*s)) - s++; + { + const char *s = chophere; + if (chopspace) { + while (*s && isSPACE(*s)) + s++; + } + sv_chop(sv,s); + SvSETMAGIC(sv); + break; } - sv_chop(sv,s); - break; + case FF_LINESNGL: + chopspace = 0; + oneline = TRUE; + goto ff_line; case FF_LINEGLOB: - item = s = SvPV(sv, len); - itemsize = len; - item_is_utf = FALSE; /* XXX is this correct? */ - if (itemsize) { - gotsome = TRUE; - send = s + itemsize; - while (s < send) { - if (*s++ == '\n') { - if (s == send) - itemsize--; - else - lines++; + oneline = FALSE; + ff_line: + { + const char *s = item = SvPV_const(sv, len); + itemsize = len; + if ((item_is_utf8 = DO_UTF8(sv))) + itemsize = sv_len_utf8(sv); + if (itemsize) { + bool chopped = FALSE; + const char *const send = s + len; + gotsome = TRUE; + chophere = s + itemsize; + while (s < send) { + if (*s++ == '\n') { + if (oneline) { + chopped = TRUE; + chophere = s; + break; + } else { + if (s == send) { + itemsize--; + chopped = TRUE; + } else + lines++; + } + } } + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + if (targ_is_utf8) + SvUTF8_on(PL_formtarget); + if (oneline) { + SvCUR_set(sv, chophere - item); + sv_catsv(PL_formtarget, sv); + SvCUR_set(sv, itemsize); + } else + sv_catsv(PL_formtarget, sv); + if (chopped) + SvCUR_set(PL_formtarget, SvCUR(PL_formtarget) - 1); + SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1); + t = SvPVX(PL_formtarget) + SvCUR(PL_formtarget); + if (item_is_utf8) + targ_is_utf8 = TRUE; } - SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget)); - sv_catpvn(PL_formtarget, item, itemsize); - SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1); - t = SvPVX(PL_formtarget) + SvCUR(PL_formtarget); + break; } - break; + case FF_0DECIMAL: + arg = *fpc++; +#if defined(USE_LONG_DOUBLE) + fmt = (arg & 256) ? "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl; +#else + fmt = (arg & 256) ? "%#0*.*f" : "%0*.*f"; +#endif + goto ff_dec; case FF_DECIMAL: - /* If the field is marked with ^ and the value is undefined, - blank it out. */ arg = *fpc++; - if ((arg & 512) && !SvOK(sv)) { - arg = fieldsize; - while (arg--) - *t++ = ' '; - break; - } - gotsome = TRUE; - value = SvNV(sv); - /* Formats aren't yet marked for locales, so assume "yes". */ - { - STORE_NUMERIC_STANDARD_SET_LOCAL(); #if defined(USE_LONG_DOUBLE) - if (arg & 256) { - sprintf(t, "%#*.*" PERL_PRIfldbl, - (int) fieldsize, (int) arg & 255, value); - } else { - sprintf(t, "%*.0" PERL_PRIfldbl, (int) fieldsize, value); - } + fmt = (arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl; #else - if (arg & 256) { - sprintf(t, "%#*.*f", - (int) fieldsize, (int) arg & 255, value); - } else { - sprintf(t, "%*.0f", - (int) fieldsize, value); - } + fmt = (arg & 256) ? "%#*.*f" : "%*.*f"; #endif - RESTORE_NUMERIC_STANDARD(); - } - t += fieldsize; - break; - - case FF_0DECIMAL: + ff_dec: /* If the field is marked with ^ and the value is undefined, blank it out. */ - arg = *fpc++; if ((arg & 512) && !SvOK(sv)) { arg = fieldsize; while (arg--) @@ -659,31 +816,22 @@ PP(pp_formline) } gotsome = TRUE; value = SvNV(sv); + /* overflow evidence */ + if (num_overflow(value, fieldsize, arg)) { + arg = fieldsize; + while (arg--) + *t++ = '#'; + break; + } /* Formats aren't yet marked for locales, so assume "yes". */ { STORE_NUMERIC_STANDARD_SET_LOCAL(); -#if defined(USE_LONG_DOUBLE) - if (arg & 256) { - sprintf(t, "%#0*.*" PERL_PRIfldbl, - (int) fieldsize, (int) arg & 255, value); -/* is this legal? I don't have long doubles */ - } else { - sprintf(t, "%0*.0" PERL_PRIfldbl, (int) fieldsize, value); - } -#else - if (arg & 256) { - sprintf(t, "%#0*.*f", - (int) fieldsize, (int) arg & 255, value); - } else { - sprintf(t, "%0*.0f", - (int) fieldsize, value); - } -#endif + sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value); RESTORE_NUMERIC_STANDARD(); } t += fieldsize; break; - + case FF_NEWLINE: f++; while (t-- > linemark && *t == ' ') ; @@ -696,13 +844,15 @@ PP(pp_formline) if (gotsome) { if (arg) { /* repeat until fields exhausted? */ *t = '\0'; - SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget)); + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); lines += FmLINES(PL_formtarget); if (lines == 200) { arg = t - linemark; if (strnEQ(linemark, linemark - arg, arg)) DIE(aTHX_ "Runaway format"); } + if (targ_is_utf8) + SvUTF8_on(PL_formtarget); FmLINES(PL_formtarget) = lines; SP = ORIGMARK; RETURNOP(cLISTOP->op_first); @@ -715,33 +865,37 @@ PP(pp_formline) break; case FF_MORE: - s = chophere; - send = item + len; - if (chopspace) { - while (*s && isSPACE(*s) && s < send) - s++; - } - if (s < send) { - arg = fieldsize - itemsize; - if (arg) { - fieldsize -= arg; - while (arg-- > 0) - *t++ = ' '; + { + const char *s = chophere; + const char *send = item + len; + if (chopspace) { + while (*s && isSPACE(*s) && s < send) + s++; } - s = t - 3; - if (strnEQ(s," ",3)) { - while (s > SvPVX(PL_formtarget) && isSPACE(s[-1])) - s--; + if (s < send) { + char *s1; + arg = fieldsize - itemsize; + if (arg) { + fieldsize -= arg; + while (arg-- > 0) + *t++ = ' '; + } + s1 = t - 3; + if (strnEQ(s1," ",3)) { + while (s1 > SvPVX_const(PL_formtarget) && isSPACE(s1[-1])) + s1--; + } + *s1++ = '.'; + *s1++ = '.'; + *s1++ = '.'; } - *s++ = '.'; - *s++ = '.'; - *s++ = '.'; + break; } - break; - case FF_END: *t = '\0'; - SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget)); + SvCUR_set(PL_formtarget, t - SvPVX_const(PL_formtarget)); + if (targ_is_utf8) + SvUTF8_on(PL_formtarget); FmLINES(PL_formtarget) += lines; SP = ORIGMARK; RETPUSHYES; @@ -751,7 +905,7 @@ PP(pp_formline) PP(pp_grepstart) { - dSP; + dVAR; dSP; SV *src; if (PL_stack_base + *PL_markstack_ptr == SP) { @@ -766,14 +920,19 @@ PP(pp_grepstart) ENTER; /* enter outer scope */ SAVETMPS; - /* SAVE_DEFSV does *not* suffice here for USE_5005THREADS */ - SAVESPTR(DEFSV); + if (PL_op->op_private & OPpGREP_LEX) + SAVESPTR(PAD_SVl(PL_op->op_targ)); + else + SAVE_DEFSV; ENTER; /* enter inner scope */ SAVEVPTR(PL_curpm); src = PL_stack_base[*PL_markstack_ptr]; SvTEMP_off(src); - DEFSV = src; + if (PL_op->op_private & OPpGREP_LEX) + PAD_SVl(PL_op->op_targ) = src; + else + DEFSV = src; PUTBACK; if (PL_op->op_type == OP_MAPSTART) @@ -788,7 +947,8 @@ PP(pp_mapstart) PP(pp_mapwhile) { - dSP; + dVAR; dSP; + const I32 gimme = GIMME_V; I32 items = (SP - PL_stack_base) - *PL_markstack_ptr; /* how many new items */ I32 count; I32 shift; @@ -799,7 +959,7 @@ PP(pp_mapwhile) ++PL_markstack_ptr[-1]; /* if there are new items, push them into the destination list */ - if (items) { + if (items && gimme != G_VOID) { /* might need to make room back there first */ if (items > PL_markstack_ptr[-1] - PL_markstack_ptr[-2]) { /* XXX this implementation is very pessimal because the stack @@ -825,7 +985,7 @@ PP(pp_mapwhile) * irrelevant. --jhi */ if (shift < count) shift = count; /* Avoid shifting too often --Ben Tilly */ - + EXTEND(SP,shift); src = SP; dst = (SP += shift); @@ -836,14 +996,24 @@ PP(pp_mapwhile) } /* copy the new items down to the destination list */ dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1; - while (items-- > 0) - *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs); + if (gimme == G_ARRAY) { + while (items-- > 0) + *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs); + } + else { + /* scalar context: we don't care about which values map returns + * (we use undef here). And so we certainly don't want to do mortal + * copies of meaningless values. */ + while (items-- > 0) { + (void)POPs; + *dst-- = &PL_sv_undef; + } + } } LEAVE; /* exit inner scope */ /* All done yet? */ if (PL_markstack_ptr[-1] > *PL_markstack_ptr) { - I32 gimme = GIMME_V; (void)POPMARK; /* pop top */ LEAVE; /* exit outer scope */ @@ -852,8 +1022,15 @@ PP(pp_mapwhile) (void)POPMARK; /* pop dst */ SP = PL_stack_base + POPMARK; /* pop original mark */ if (gimme == G_SCALAR) { - dTARGET; - XPUSHi(items); + if (PL_op->op_private & OPpGREP_LEX) { + SV* sv = sv_newmortal(); + sv_setiv(sv, items); + PUSHs(sv); + } + else { + dTARGET; + XPUSHi(items); + } } else if (gimme == G_ARRAY) SP += items; @@ -868,7 +1045,10 @@ PP(pp_mapwhile) /* set $_ to the new source item */ src = PL_stack_base[PL_markstack_ptr[-1]]; SvTEMP_off(src); - DEFSV = src; + if (PL_op->op_private & OPpGREP_LEX) + PAD_SVl(PL_op->op_targ) = src; + else + DEFSV = src; RETURNOP(cLOGOP->op_other); } @@ -895,21 +1075,22 @@ PP(pp_flip) } else { dTOPss; - SV *targ = PAD_SV(PL_op->op_targ); - int flip = 0; + SV * const targ = PAD_SV(PL_op->op_targ); + int flip = 0; - if (PL_op->op_private & OPpFLIP_LINENUM) { + if (PL_op->op_private & OPpFLIP_LINENUM) { if (GvIO(PL_last_in_gv)) { flip = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv)); } else { - GV *gv = gv_fetchpv(".", TRUE, SVt_PV); - if (gv && GvSV(gv)) flip = SvIV(sv) == SvIV(GvSV(gv)); + GV * const gv = gv_fetchpv(".", TRUE, SVt_PV); + if (gv && GvSV(gv)) + flip = SvIV(sv) == SvIV(GvSV(gv)); } - } else { - flip = SvTRUE(sv); - } - if (flip) { + } else { + flip = SvTRUE(sv); + } + if (flip) { sv_setiv(PAD_SV(cUNOP->op_first->op_targ), 1); if (PL_op->op_flags & OPf_SPECIAL) { sv_setiv(targ, 1); @@ -922,37 +1103,38 @@ PP(pp_flip) RETURNOP(((LOGOP*)cUNOP->op_first)->op_other); } } - sv_setpv(TARG, ""); + sv_setpvn(TARG, "", 0); SETs(targ); RETURN; } } +/* This code tries to decide if "$left .. $right" should use the + magical string increment, or if the range is numeric (we make + an exception for .."0" [#18165]). AMS 20021031. */ + +#define RANGE_IS_NUMERIC(left,right) ( \ + SvNIOKp(left) || (SvOK(left) && !SvPOKp(left)) || \ + SvNIOKp(right) || (SvOK(right) && !SvPOKp(right)) || \ + (((!SvOK(left) && SvOK(right)) || ((!SvOK(left) || \ + looks_like_number(left)) && SvPOKp(left) && *SvPVX_const(left) != '0')) \ + && (!SvOK(right) || looks_like_number(right)))) + PP(pp_flop) { dSP; if (GIMME == G_ARRAY) { dPOPPOPssrl; - register I32 i, j; - register SV *sv; - I32 max; - - if (SvGMAGICAL(left)) - mg_get(left); - if (SvGMAGICAL(right)) - mg_get(right); - - /* This code tries to decide if "$left .. $right" should use the - magical string increment, or if the range is numeric (we make - an exception for .."0" [#18165]). AMS 20021031. */ - - if (SvNIOKp(left) || !SvPOKp(left) || - SvNIOKp(right) || !SvPOKp(right) || - (looks_like_number(left) && *SvPVX(left) != '0' && - looks_like_number(right))) - { - if (SvNV(left) < IV_MIN || SvNV(right) > IV_MAX) + + SvGETMAGIC(left); + SvGETMAGIC(right); + + if (RANGE_IS_NUMERIC(left,right)) { + register IV i, j; + IV max; + if ((SvOK(left) && SvNV(left) < IV_MIN) || + (SvOK(right) && SvNV(right) > IV_MAX)) DIE(aTHX_ "Range iterator outside integer range"); i = SvIV(left); max = SvIV(right); @@ -964,20 +1146,20 @@ PP(pp_flop) else j = 0; while (j--) { - sv = sv_2mortal(newSViv(i++)); + SV * const sv = sv_2mortal(newSViv(i++)); PUSHs(sv); } } else { - SV *final = sv_mortalcopy(right); - STRLEN len, n_a; - char *tmps = SvPV(final, len); + SV * const final = sv_mortalcopy(right); + STRLEN len; + const char * const tmps = SvPV_const(final, len); - sv = sv_mortalcopy(left); - SvPV_force(sv,n_a); + SV *sv = sv_mortalcopy(left); + SvPV_force_nolen(sv); while (!SvNIOKp(sv) && SvCUR(sv) <= len) { XPUSHs(sv); - if (strEQ(SvPVX(sv),tmps)) + if (strEQ(SvPVX_const(sv),tmps)) break; sv = sv_2mortal(newSVsv(sv)); sv_inc(sv); @@ -986,7 +1168,7 @@ PP(pp_flop) } else { dTOPss; - SV *targ = PAD_SV(cUNOP->op_first->op_targ); + SV * const targ = PAD_SV(cUNOP->op_first->op_targ); int flop = 0; sv_inc(targ); @@ -995,7 +1177,7 @@ PP(pp_flop) flop = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv)); } else { - GV *gv = gv_fetchpv(".", TRUE, SVt_PV); + GV * const gv = gv_fetchpv(".", TRUE, SVt_PV); if (gv && GvSV(gv)) flop = SvIV(sv) == SvIV(GvSV(gv)); } } @@ -1005,7 +1187,7 @@ PP(pp_flop) if (flop) { sv_setiv(PAD_SV(((UNOP*)cUNOP->op_first)->op_first->op_targ), 0); - sv_catpv(targ, "E0"); + sv_catpvn(targ, "E0", 2); } SETs(targ); } @@ -1015,43 +1197,37 @@ PP(pp_flop) /* Control. */ +static const char * const context_name[] = { + "pseudo-block", + "subroutine", + "eval", + "loop", + "substitution", + "block", + "format" +}; + STATIC I32 -S_dopoptolabel(pTHX_ char *label) +S_dopoptolabel(pTHX_ const char *label) { register I32 i; - register PERL_CONTEXT *cx; for (i = cxstack_ix; i >= 0; i--) { - cx = &cxstack[i]; + register const PERL_CONTEXT * const cx = &cxstack[i]; switch (CxTYPE(cx)) { case CXt_SUBST: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting substitution via %s", - OP_NAME(PL_op)); - break; case CXt_SUB: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting subroutine via %s", - OP_NAME(PL_op)); - break; case CXt_FORMAT: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting format via %s", - OP_NAME(PL_op)); - break; case CXt_EVAL: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting eval via %s", - OP_NAME(PL_op)); - break; case CXt_NULL: if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting pseudo-block via %s", - OP_NAME(PL_op)); - return -1; + Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting %s via %s", + context_name[CxTYPE(cx)], OP_NAME(PL_op)); + if (CxTYPE(cx) == CXt_NULL) + return -1; + break; case CXt_LOOP: - if (!cx->blk_loop.label || - strNE(label, cx->blk_loop.label) ) { + if ( !cx->blk_loop.label || strNE(label, cx->blk_loop.label) ) { DEBUG_l(Perl_deb(aTHX_ "(Skipping label #%ld %s)\n", (long)i, cx->blk_loop.label)); continue; @@ -1066,16 +1242,14 @@ S_dopoptolabel(pTHX_ char *label) I32 Perl_dowantarray(pTHX) { - I32 gimme = block_gimme(); + const I32 gimme = block_gimme(); return (gimme == G_VOID) ? G_SCALAR : gimme; } I32 Perl_block_gimme(pTHX) { - I32 cxix; - - cxix = dopoptosub(cxstack_ix); + const I32 cxix = dopoptosub(cxstack_ix); if (cxix < 0) return G_VOID; @@ -1096,9 +1270,7 @@ Perl_block_gimme(pTHX) I32 Perl_is_lvalue_sub(pTHX) { - I32 cxix; - - cxix = dopoptosub(cxstack_ix); + const I32 cxix = dopoptosub(cxstack_ix); assert(cxix >= 0); /* We should only be called from inside subs */ if (cxstack[cxix].blk_sub.lval && CvLVALUE(cxstack[cxix].blk_sub.cv)) @@ -1114,12 +1286,11 @@ S_dopoptosub(pTHX_ I32 startingblock) } STATIC I32 -S_dopoptosub_at(pTHX_ PERL_CONTEXT *cxstk, I32 startingblock) +S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) { I32 i; - register PERL_CONTEXT *cx; for (i = startingblock; i >= 0; i--) { - cx = &cxstk[i]; + register const PERL_CONTEXT * const cx = &cxstk[i]; switch (CxTYPE(cx)) { default: continue; @@ -1137,9 +1308,8 @@ STATIC I32 S_dopoptoeval(pTHX_ I32 startingblock) { I32 i; - register PERL_CONTEXT *cx; for (i = startingblock; i >= 0; i--) { - cx = &cxstack[i]; + register const PERL_CONTEXT *cx = &cxstack[i]; switch (CxTYPE(cx)) { default: continue; @@ -1155,35 +1325,20 @@ STATIC I32 S_dopoptoloop(pTHX_ I32 startingblock) { I32 i; - register PERL_CONTEXT *cx; for (i = startingblock; i >= 0; i--) { - cx = &cxstack[i]; + register const PERL_CONTEXT * const cx = &cxstack[i]; switch (CxTYPE(cx)) { case CXt_SUBST: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting substitution via %s", - OP_NAME(PL_op)); - break; case CXt_SUB: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting subroutine via %s", - OP_NAME(PL_op)); - break; case CXt_FORMAT: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting format via %s", - OP_NAME(PL_op)); - break; case CXt_EVAL: - if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting eval via %s", - OP_NAME(PL_op)); - break; case CXt_NULL: if (ckWARN(WARN_EXITING)) - Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting pseudo-block via %s", - OP_NAME(PL_op)); - return -1; + Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting %s via %s", + context_name[CxTYPE(cx)], OP_NAME(PL_op)); + if ((CxTYPE(cx)) == CXt_NULL) + return -1; + break; case CXt_LOOP: DEBUG_l( Perl_deb(aTHX_ "(Found loop #%ld)\n", (long)i)); return i; @@ -1195,12 +1350,11 @@ S_dopoptoloop(pTHX_ I32 startingblock) void Perl_dounwind(pTHX_ I32 cxix) { - register PERL_CONTEXT *cx; I32 optype; while (cxstack_ix > cxix) { SV *sv; - cx = &cxstack[cxstack_ix]; + register PERL_CONTEXT *cx = &cxstack[cxstack_ix]; DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n", (long) cxstack_ix, PL_block_type[CxTYPE(cx)])); /* Note: we don't need to restore the base context info till the end. */ @@ -1226,6 +1380,7 @@ Perl_dounwind(pTHX_ I32 cxix) } cxstack_ix--; } + PERL_UNUSED_VAR(optype); } void @@ -1241,28 +1396,25 @@ Perl_qerror(pTHX_ SV *err) } OP * -Perl_die_where(pTHX_ char *message, STRLEN msglen) +Perl_die_where(pTHX_ const char *message, STRLEN msglen) { - STRLEN n_a; - IO *io; - MAGIC *mg; + dVAR; if (PL_in_eval) { I32 cxix; - register PERL_CONTEXT *cx; I32 gimme; - SV **newsp; if (message) { if (PL_in_eval & EVAL_KEEPERR) { - static char prefix[] = "\t(in cleanup) "; - SV *err = ERRSV; - char *e = Nullch; + static const char prefix[] = "\t(in cleanup) "; + SV * const err = ERRSV; + const char *e = Nullch; if (!SvPOK(err)) - sv_setpv(err,""); + sv_setpvn(err,"",0); else if (SvCUR(err) >= sizeof(prefix)+msglen-1) { - e = SvPV(err, n_a); - e += n_a - msglen; + STRLEN len; + e = SvPV_const(err, len); + e += len - msglen; if (*e != *message || strNE(e,message)) e = Nullch; } @@ -1271,8 +1423,8 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) sv_catpvn(err, prefix, sizeof(prefix)-1); sv_catpvn(err, message, msglen); if (ckWARN(WARN_MISC)) { - STRLEN start = SvCUR(err)-msglen-sizeof(prefix)+1; - Perl_warner(aTHX_ packWARN(WARN_MISC), SvPVX(err)+start); + const STRLEN start = SvCUR(err)-msglen-sizeof(prefix)+1; + Perl_warner(aTHX_ packWARN(WARN_MISC), SvPVX_const(err)+start); } } } @@ -1280,8 +1432,6 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) sv_setpvn(ERRSV, message, msglen); } } - else - message = SvPVx(ERRSV, msglen); while ((cxix = dopoptoeval(cxstack_ix)) < 0 && PL_curstackinfo->si_prev) @@ -1292,12 +1442,16 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) if (cxix >= 0) { I32 optype; + register PERL_CONTEXT *cx; + SV **newsp; if (cxix < cxstack_ix) dounwind(cxix); POPBLOCK(cx,PL_curpm); if (CxTYPE(cx) != CXt_EVAL) { + if (!message) + message = SvPVx_const(ERRSV, msglen); PerlIO_write(Perl_error_log, "panic: die ", 11); PerlIO_write(Perl_error_log, message, msglen); my_exit(1); @@ -1317,40 +1471,21 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) PL_curcop = cx->blk_oldcop; if (optype == OP_REQUIRE) { - char* msg = SvPVx(ERRSV, n_a); + const char* const msg = SvPVx_nolen_const(ERRSV); + SV * const nsv = cx->blk_eval.old_namesv; + (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), + &PL_sv_undef, 0); DIE(aTHX_ "%sCompilation failed in require", *msg ? msg : "Unknown error\n"); } - return pop_return(); + assert(CxTYPE(cx) == CXt_EVAL); + return cx->blk_eval.retop; } } if (!message) - message = SvPVx(ERRSV, msglen); - - /* if STDERR is tied, print to it instead */ - if (PL_stderrgv && (io = GvIOp(PL_stderrgv)) - && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) { - dSP; ENTER; - PUSHMARK(SP); - XPUSHs(SvTIED_obj((SV*)io, mg)); - XPUSHs(sv_2mortal(newSVpvn(message, msglen))); - PUTBACK; - call_method("PRINT", G_SCALAR); - LEAVE; - } - else { -#ifdef USE_SFIO - /* SFIO can really mess with your errno */ - int e = errno; -#endif - PerlIO *serr = Perl_error_log; + message = SvPVx_const(ERRSV, msglen); - PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen); - (void)PerlIO_flush(serr); -#ifdef USE_SFIO - errno = e; -#endif - } + write_to_stderr(message, msglen); my_failure_exit(); /* NOTREACHED */ return 0; @@ -1407,8 +1542,7 @@ PP(pp_dorassign) RETURN; break; default: - if (SvGMAGICAL(sv)) - mg_get(sv); + SvGETMAGIC(sv); if (SvOK(sv)) RETURN; } @@ -1420,13 +1554,11 @@ PP(pp_caller) { dSP; register I32 cxix = dopoptosub(cxstack_ix); - register PERL_CONTEXT *cx; - register PERL_CONTEXT *ccstack = cxstack; - PERL_SI *top_si = PL_curstackinfo; - I32 dbcxix; + register const PERL_CONTEXT *cx; + register const PERL_CONTEXT *ccstack = cxstack; + const PERL_SI *top_si = PL_curstackinfo; I32 gimme; - char *stashname; - SV *sv; + const char *stashname; I32 count = 0; if (MAXARG) @@ -1446,7 +1578,8 @@ PP(pp_caller) } RETURN; } - if (PL_DBsub && cxix >= 0 && + /* caller() should not report the automatic calls to &DB::sub */ + if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub)) count++; if (!count--) @@ -1456,10 +1589,11 @@ PP(pp_caller) cx = &ccstack[cxix]; if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { - dbcxix = dopoptosub_at(ccstack, cxix - 1); + const I32 dbcxix = dopoptosub_at(ccstack, cxix - 1); /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the field below is defined for any cx. */ - if (PL_DBsub && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) + /* caller() should not report the automatic calls to &DB::sub */ + if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) cx = &ccstack[dbcxix]; } @@ -1490,7 +1624,7 @@ PP(pp_caller) GV *cvgv = CvGV(ccstack[cxix].blk_sub.cv); /* So is ccstack[dbcxix]. */ if (isGV(cvgv)) { - sv = NEWSV(49, 0); + SV * const sv = NEWSV(49, 0); gv_efullname3(sv, cvgv, Nullch); PUSHs(sv_2mortal(sv)); PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs))); @@ -1533,8 +1667,8 @@ PP(pp_caller) if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.hasargs && CopSTASH_eq(PL_curcop, PL_debstash)) { - AV *ary = cx->blk_sub.argarray; - int off = AvARRAY(ary) - AvALLOC(ary); + AV * const ary = cx->blk_sub.argarray; + const int off = AvARRAY(ary) - AvALLOC(ary); if (!PL_dbargs) { GV* tmpgv; @@ -1562,8 +1696,18 @@ PP(pp_caller) (old_warnings == pWARN_STD && (PL_dowarn & G_WARN_ON) == 0)) mask = newSVpvn(WARN_NONEstring, WARNsize) ; else if (old_warnings == pWARN_ALL || - (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) - mask = newSVpvn(WARN_ALLstring, WARNsize) ; + (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) { + /* Get the bit mask for $warnings::Bits{all}, because + * it could have been extended by warnings::register */ + SV **bits_all; + HV *bits = get_hv("warnings::Bits", FALSE); + if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) { + mask = newSVsv(*bits_all); + } + else { + mask = newSVpvn(WARN_ALLstring, WARNsize) ; + } + } else mask = newSVsv(old_warnings); PUSHs(sv_2mortal(mask)); @@ -1574,13 +1718,12 @@ PP(pp_caller) PP(pp_reset) { dSP; - char *tmps; - STRLEN n_a; + const char *tmps; if (MAXARG < 1) tmps = ""; else - tmps = POPpx; + tmps = POPpconstx; sv_reset(tmps, CopSTASH(PL_curcop)); PUSHs(&PL_sv_yes); RETURN; @@ -1595,17 +1738,19 @@ PP(pp_lineseq) PP(pp_dbstate) { + dVAR; PL_curcop = (COP*)PL_op; TAINT_NOT; /* Each statement is presumed innocent */ PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp; FREETMPS; - if (PL_op->op_private || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace)) + if (PL_op->op_flags & OPf_SPECIAL /* breakpoint */ + || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace)) { dSP; register CV *cv; register PERL_CONTEXT *cx; - I32 gimme = G_ARRAY; + const I32 gimme = G_ARRAY; U8 hasargs; GV *gv; @@ -1627,13 +1772,24 @@ PP(pp_dbstate) hasargs = 0; SPAGAIN; - push_return(PL_op->op_next); - PUSHBLOCK(cx, CXt_SUB, SP); - PUSHSUB(cx); - CvDEPTH(cv)++; - (void)SvREFCNT_inc(cv); - PAD_SET_CUR(CvPADLIST(cv),1); - RETURNOP(CvSTART(cv)); + if (CvXSUB(cv)) { + CvDEPTH(cv)++; + PUSHMARK(SP); + (void)(*CvXSUB(cv))(aTHX_ cv); + CvDEPTH(cv)--; + FREETMPS; + LEAVE; + return NORMAL; + } + else { + PUSHBLOCK(cx, CXt_SUB, SP); + PUSHSUB_DB(cx); + cx->blk_sub.retop = PL_op->op_next; + CvDEPTH(cv)++; + SAVECOMPPAD(); + PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1); + RETURNOP(CvSTART(cv)); + } } else return NORMAL; @@ -1646,9 +1802,9 @@ PP(pp_scope) PP(pp_enteriter) { - dSP; dMARK; + dVAR; dSP; dMARK; register PERL_CONTEXT *cx; - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; SV **svp; U32 cxtype = CXt_LOOP; #ifdef USE_ITHREADS @@ -1659,6 +1815,11 @@ PP(pp_enteriter) SAVETMPS; if (PL_op->op_targ) { + if (PL_op->op_private & OPpLVAL_INTRO) { /* for my $x (...) */ + SvPADSTALE_off(PAD_SVl(PL_op->op_targ)); + SAVESETSVFLAGS(PAD_SVl(PL_op->op_targ), + SVs_PADSTALE, SVs_PADSTALE); + } #ifndef USE_ITHREADS svp = &PAD_SVl(PL_op->op_targ); /* "my" variable */ SAVESPTR(*svp); @@ -1690,26 +1851,42 @@ PP(pp_enteriter) cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs); if (SvTYPE(cx->blk_loop.iterary) != SVt_PVAV) { dPOPss; - /* See comment in pp_flop() */ - if (SvNIOKp(sv) || !SvPOKp(sv) || - SvNIOKp(cx->blk_loop.iterary) || !SvPOKp(cx->blk_loop.iterary) || - (looks_like_number(sv) && *SvPVX(sv) != '0' && - looks_like_number((SV*)cx->blk_loop.iterary))) - { - if (SvNV(sv) < IV_MIN || - SvNV((SV*)cx->blk_loop.iterary) >= IV_MAX) - DIE(aTHX_ "Range iterator outside integer range"); - cx->blk_loop.iterix = SvIV(sv); - cx->blk_loop.itermax = SvIV((SV*)cx->blk_loop.iterary); + SV *right = (SV*)cx->blk_loop.iterary; + SvGETMAGIC(sv); + SvGETMAGIC(right); + if (RANGE_IS_NUMERIC(sv,right)) { + if ((SvOK(sv) && SvNV(sv) < IV_MIN) || + (SvOK(right) && SvNV(right) >= IV_MAX)) + DIE(aTHX_ "Range iterator outside integer range"); + cx->blk_loop.iterix = SvIV(sv); + cx->blk_loop.itermax = SvIV(right); +#ifdef DEBUGGING + /* for correct -Dstv display */ + cx->blk_oldsp = sp - PL_stack_base; +#endif } - else + else { cx->blk_loop.iterlval = newSVsv(sv); + (void) SvPV_force_nolen(cx->blk_loop.iterlval); + (void) SvPV_nolen_const(right); + } + } + else if (PL_op->op_private & OPpITER_REVERSED) { + cx->blk_loop.itermax = -1; + cx->blk_loop.iterix = AvFILL(cx->blk_loop.iterary); + } } else { cx->blk_loop.iterary = PL_curstack; AvFILLp(PL_curstack) = SP - PL_stack_base; - cx->blk_loop.iterix = MARK - PL_stack_base; + if (PL_op->op_private & OPpITER_REVERSED) { + cx->blk_loop.itermax = MARK - PL_stack_base; + cx->blk_loop.iterix = cx->blk_oldsp; + } + else { + cx->blk_loop.iterix = MARK - PL_stack_base; + } } RETURN; @@ -1717,9 +1894,9 @@ PP(pp_enteriter) PP(pp_enterloop) { - dSP; + dVAR; dSP; register PERL_CONTEXT *cx; - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; ENTER; SAVETMPS; @@ -1733,7 +1910,7 @@ PP(pp_enterloop) PP(pp_leaveloop) { - dSP; + dVAR; dSP; register PERL_CONTEXT *cx; I32 gimme; SV **newsp; @@ -1741,6 +1918,7 @@ PP(pp_leaveloop) SV **mark; POPBLOCK(cx,newpm); + assert(CxTYPE(cx) == CXt_LOOP); mark = newsp; newsp = PL_stack_base + cx->blk_loop.resetsp; @@ -1773,7 +1951,7 @@ PP(pp_leaveloop) PP(pp_return) { - dSP; dMARK; + dVAR; dSP; dMARK; I32 cxix; register PERL_CONTEXT *cx; bool popsub2 = FALSE; @@ -1783,6 +1961,7 @@ PP(pp_return) PMOP *newpm; I32 optype = 0; SV *sv; + OP *retop; if (PL_curstackinfo->si_type == PERLSI_SORT) { if (cxstack_ix == PL_sortcxix @@ -1806,11 +1985,14 @@ PP(pp_return) switch (CxTYPE(cx)) { case CXt_SUB: popsub2 = TRUE; + retop = cx->blk_sub.retop; + cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */ break; case CXt_EVAL: if (!(PL_in_eval & EVAL_KEEPERR)) clear_errsv = TRUE; POPEVAL(cx); + retop = cx->blk_eval.retop; if (CxTRYBLOCK(cx)) break; lex_end(); @@ -1818,13 +2000,14 @@ PP(pp_return) (MARK == SP || (gimme == G_SCALAR && !SvTRUE(*SP))) ) { /* Unassume the success we assumed earlier. */ - SV *nsv = cx->blk_eval.old_namesv; - (void)hv_delete(GvHVn(PL_incgv), SvPVX(nsv), SvCUR(nsv), G_DISCARD); - DIE(aTHX_ "%s did not return a true value", SvPVX(nsv)); + SV * const nsv = cx->blk_eval.old_namesv; + (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD); + DIE(aTHX_ "%"SVf" did not return a true value", nsv); } break; case CXt_FORMAT: POPFORMAT(cx); + retop = cx->blk_sub.retop; break; default: DIE(aTHX_ "panic: return"); @@ -1865,24 +2048,25 @@ PP(pp_return) } PL_stack_sp = newsp; + LEAVE; /* Stack values are safe: */ if (popsub2) { + cxstack_ix--; POPSUB(cx,sv); /* release CV and @_ ... */ } else sv = Nullsv; PL_curpm = newpm; /* ... and pop $1 et al */ - LEAVE; LEAVESUB(sv); if (clear_errsv) - sv_setpv(ERRSV,""); - return pop_return(); + sv_setpvn(ERRSV,"",0); + return retop; } PP(pp_last) { - dSP; + dVAR; dSP; I32 cxix; register PERL_CONTEXT *cx; I32 pop2 = 0; @@ -1894,6 +2078,7 @@ PP(pp_last) SV **mark; SV *sv = Nullsv; + if (PL_op->op_flags & OPf_SPECIAL) { cxix = dopoptoloop(cxstack_ix); if (cxix < 0) @@ -1908,6 +2093,7 @@ PP(pp_last) dounwind(cxix); POPBLOCK(cx,newpm); + cxstack_ix++; /* temporarily protect top context */ mark = newsp; switch (CxTYPE(cx)) { case CXt_LOOP: @@ -1917,15 +2103,15 @@ PP(pp_last) break; case CXt_SUB: pop2 = CXt_SUB; - nextop = pop_return(); + nextop = cx->blk_sub.retop; break; case CXt_EVAL: POPEVAL(cx); - nextop = pop_return(); + nextop = cx->blk_eval.retop; break; case CXt_FORMAT: POPFORMAT(cx); - nextop = pop_return(); + nextop = cx->blk_sub.retop; break; default: DIE(aTHX_ "panic: last"); @@ -1949,6 +2135,8 @@ PP(pp_last) SP = newsp; PUTBACK; + LEAVE; + cxstack_ix--; /* Stack values are safe: */ switch (pop2) { case CXt_LOOP: @@ -1961,13 +2149,15 @@ PP(pp_last) } PL_curpm = newpm; /* ... and pop $1 et al */ - LEAVE; LEAVESUB(sv); + PERL_UNUSED_VAR(optype); + PERL_UNUSED_VAR(gimme); return nextop; } PP(pp_next) { + dVAR; I32 cxix; register PERL_CONTEXT *cx; I32 inner; @@ -1991,14 +2181,17 @@ PP(pp_next) TOPBLOCK(cx); if (PL_scopestack_ix < inner) leave_scope(PL_scopestack[PL_scopestack_ix]); + PL_curcop = cx->blk_oldcop; return cx->blk_loop.next_op; } PP(pp_redo) { + dVAR; I32 cxix; register PERL_CONTEXT *cx; I32 oldsave; + OP* redo_op; if (PL_op->op_flags & OPf_SPECIAL) { cxix = dopoptoloop(cxstack_ix); @@ -2013,24 +2206,34 @@ PP(pp_redo) if (cxix < cxstack_ix) dounwind(cxix); + redo_op = cxstack[cxix].blk_loop.redo_op; + if (redo_op->op_type == OP_ENTER) { + /* pop one less context to avoid $x being freed in while (my $x..) */ + cxstack_ix++; + assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_BLOCK); + redo_op = redo_op->op_next; + } + TOPBLOCK(cx); oldsave = PL_scopestack[PL_scopestack_ix - 1]; LEAVE_SCOPE(oldsave); - return cx->blk_loop.redo_op; + FREETMPS; + PL_curcop = cx->blk_oldcop; + return redo_op; } STATIC OP * -S_dofindlabel(pTHX_ OP *o, char *label, OP **opstack, OP **oplimit) +S_dofindlabel(pTHX_ OP *o, const char *label, OP **opstack, OP **oplimit) { - OP *kid = Nullop; OP **ops = opstack; - static char too_deep[] = "Target of goto is too deeply nested"; + static const char too_deep[] = "Target of goto is too deeply nested"; if (ops >= oplimit) Perl_croak(aTHX_ too_deep); if (o->op_type == OP_LEAVE || o->op_type == OP_SCOPE || o->op_type == OP_LEAVELOOP || + o->op_type == OP_LEAVESUB || o->op_type == OP_LEAVETRY) { *ops++ = cUNOPo->op_first; @@ -2039,6 +2242,7 @@ S_dofindlabel(pTHX_ OP *o, char *label, OP **opstack, OP **oplimit) } *ops = 0; if (o->op_flags & OPf_KIDS) { + OP *kid; /* First try all the kids at this level, since that's likeliest. */ for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { if ((kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) && @@ -2073,20 +2277,18 @@ PP(pp_dump) PP(pp_goto) { - dSP; + dVAR; dSP; OP *retop = 0; I32 ix; register PERL_CONTEXT *cx; #define GOTO_DEPTH 64 OP *enterops[GOTO_DEPTH]; - char *label; - int do_dump = (PL_op->op_type == OP_DUMP); - static char must_have_label[] = "goto must have label"; + const char *label = 0; + const bool do_dump = (PL_op->op_type == OP_DUMP); + static const char must_have_label[] = "goto must have label"; - label = 0; if (PL_op->op_flags & OPf_STACKED) { - SV *sv = POPs; - STRLEN n_a; + SV * const sv = POPs; /* This egregious kludge implements goto &subroutine */ if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV) { @@ -2096,12 +2298,13 @@ PP(pp_goto) SV** mark; I32 items = 0; I32 oldsave; + bool reified = 0; retry: if (!CvROOT(cv) && !CvXSUB(cv)) { - GV *gv = CvGV(cv); - GV *autogv; + const GV * const gv = CvGV(cv); if (gv) { + GV *autogv; SV *tmpstr; /* autoloaded stub? */ if (cv != GvCV(gv) && (cv = GvCV(gv))) @@ -2112,50 +2315,56 @@ PP(pp_goto) goto retry; tmpstr = sv_newmortal(); gv_efullname3(tmpstr, gv, Nullch); - DIE(aTHX_ "Goto undefined subroutine &%s",SvPVX(tmpstr)); + DIE(aTHX_ "Goto undefined subroutine &%"SVf"",tmpstr); } DIE(aTHX_ "Goto undefined subroutine"); } /* First do some returnish stuff. */ + (void)SvREFCNT_inc(cv); /* avoid premature free during unwind */ + FREETMPS; cxix = dopoptosub(cxstack_ix); if (cxix < 0) DIE(aTHX_ "Can't goto subroutine outside a subroutine"); if (cxix < cxstack_ix) dounwind(cxix); TOPBLOCK(cx); - if (CxREALEVAL(cx)) - DIE(aTHX_ "Can't goto subroutine from an eval-string"); - mark = PL_stack_sp; + SPAGAIN; + /* ban goto in eval: see <20050521150056.GC20213@iabyn.com> */ + if (CxTYPE(cx) == CXt_EVAL) { + if (CxREALEVAL(cx)) + DIE(aTHX_ "Can't goto subroutine from an eval-string"); + else + DIE(aTHX_ "Can't goto subroutine from an eval-block"); + } if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.hasargs) { /* put @_ back onto stack */ AV* av = cx->blk_sub.argarray; - + items = AvFILLp(av) + 1; - PL_stack_sp++; - EXTEND(PL_stack_sp, items); /* @_ could have been extended. */ - Copy(AvARRAY(av), PL_stack_sp, items, SV*); - PL_stack_sp += items; + EXTEND(SP, items+1); /* @_ could have been extended. */ + Copy(AvARRAY(av), SP + 1, items, SV*); SvREFCNT_dec(GvAV(PL_defgv)); GvAV(PL_defgv) = cx->blk_sub.savearray; + CLEAR_ARGARRAY(av); /* abandon @_ if it got reified */ if (AvREAL(av)) { - (void)sv_2mortal((SV*)av); /* delay until return */ + reified = 1; + SvREFCNT_dec(av); av = newAV(); av_extend(av, items-1); - AvFLAGS(av) = AVf_REIFY; + AvREIFY_only(av); PAD_SVl(0) = (SV*)(cx->blk_sub.argarray = av); } } else if (CvXSUB(cv)) { /* put GvAV(defgv) back onto stack */ - AV* av; - av = GvAV(PL_defgv); + AV* const av = GvAV(PL_defgv); items = AvFILLp(av) + 1; - PL_stack_sp++; - EXTEND(PL_stack_sp, items); /* @_ could have been extended. */ - Copy(AvARRAY(av), PL_stack_sp, items, SV*); - PL_stack_sp += items; + EXTEND(SP, items+1); /* @_ could have been extended. */ + Copy(AvARRAY(av), SP + 1, items, SV*); } + mark = SP; + SP += items; if (CxTYPE(cx) == CXt_SUB && !(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth)) SvREFCNT_dec(cx->blk_sub.cv); @@ -2164,7 +2373,14 @@ PP(pp_goto) /* Now do some callish stuff. */ SAVETMPS; + SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */ if (CvXSUB(cv)) { + OP* retop = cx->blk_sub.retop; + if (reified) { + I32 index; + for (index=0; indexblk_sub.hasargs); + pad_push(padlist, CvDEPTH(cv)); } - PAD_SET_CUR(padlist, CvDEPTH(cv)); + SAVECOMPPAD(); + PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); if (cx->blk_sub.hasargs) { AV* av = (AV*)PAD_SVl(0); @@ -2224,24 +2443,29 @@ PP(pp_goto) GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av); CX_CURPAD_SAVE(cx->blk_sub); cx->blk_sub.argarray = av; - ++mark; if (items >= AvMAX(av) + 1) { ary = AvALLOC(av); if (AvARRAY(av) != ary) { AvMAX(av) += AvARRAY(av) - AvALLOC(av); - SvPVX(av) = (char*)ary; + SvPV_set(av, (char*)ary); } if (items >= AvMAX(av) + 1) { AvMAX(av) = items - 1; Renew(ary,items+1,SV*); AvALLOC(av) = ary; - SvPVX(av) = (char*)ary; + SvPV_set(av, (char*)ary); } } + ++mark; Copy(mark,AvARRAY(av),items,SV*); AvFILLp(av) = items - 1; assert(!AvREAL(av)); + if (reified) { + /* transfer 'ownership' of refcnts to new @_ */ + AvREAL_on(av); + AvREIFY_off(av); + } while (items--) { if (*mark) SvTEMP_off(*mark); @@ -2253,13 +2477,17 @@ PP(pp_goto) * We do not care about using sv to call CV; * it's for informational purposes only. */ - SV *sv = GvSV(PL_DBsub); + SV * const sv = GvSV(PL_DBsub); CV *gotocv; - + + save_item(sv); if (PERLDB_SUB_NN) { - SvIVX(sv) = PTR2IV(cv); /* Already upgraded, saved */ + const int type = SvTYPE(sv); + if (type < SVt_PVIV && type != SVt_IV) + sv_upgrade(sv, SVt_PVIV); + (void)SvIOK_on(sv); + SvIV_set(sv, PTR2IV(cv)); /* Do it the quickest way */ } else { - save_item(sv); gv_efullname3(sv, CvGV(cv), Nullch); } if ( PERLDB_GOTO @@ -2273,7 +2501,7 @@ PP(pp_goto) } } else { - label = SvPV(sv,n_a); + label = SvPV_nolen_const(sv); if (!(do_dump || *label)) DIE(aTHX_ must_have_label); } @@ -2288,6 +2516,7 @@ PP(pp_goto) if (label && *label) { OP *gotoprobe = 0; bool leaving_eval = FALSE; + bool in_block = FALSE; PERL_CONTEXT *last_eval_cx = 0; /* find label */ @@ -2299,7 +2528,7 @@ PP(pp_goto) switch (CxTYPE(cx)) { case CXt_EVAL: leaving_eval = TRUE; - if (CxREALEVAL(cx)) { + if (!CxTRYBLOCK(cx)) { gotoprobe = (last_eval_cx ? last_eval_cx->blk_eval.old_eval_root : PL_eval_root); @@ -2313,9 +2542,10 @@ PP(pp_goto) case CXt_SUBST: continue; case CXt_BLOCK: - if (ix) + if (ix) { gotoprobe = cx->blk_oldcop->op_sibling; - else + in_block = TRUE; + } else gotoprobe = PL_main_root; break; case CXt_SUB: @@ -2372,7 +2602,8 @@ PP(pp_goto) if (*enterops && enterops[1]) { OP *oldop = PL_op; - for (ix = 1; enterops[ix]; ix++) { + ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1; + for (; enterops[ix]; ix++) { PL_op = enterops[ix]; /* Eventually we may want to stack the needed arguments * for each op. For now, we punt on the hard ones. */ @@ -2425,7 +2656,7 @@ PP(pp_exit) PP(pp_nswitch) { dSP; - NV value = SvNVx(GvSV(cCOP->cop_gv)); + const NV value = SvNVx(GvSV(cCOP->cop_gv)); register I32 match = I_32(value); if (value < 0.0) { @@ -2449,8 +2680,7 @@ PP(pp_cswitch) if (PL_multiline) PL_op = PL_op->op_next; /* can't assume anything */ else { - STRLEN n_a; - match = *(SvPVx(GvSV(cCOP->cop_gv), n_a)) & 255; + match = *(SvPVx_nolen_const(GvSV(cCOP->cop_gv))) & 255; match -= cCOP->uop.scop.scop_offset; if (match < 0) match = 0; @@ -2467,13 +2697,13 @@ PP(pp_cswitch) STATIC void S_save_lines(pTHX_ AV *array, SV *sv) { - register char *s = SvPVX(sv); - register char *send = SvPVX(sv) + SvCUR(sv); - register char *t; - register I32 line = 1; + const char *s = SvPVX_const(sv); + const char * const send = SvPVX_const(sv) + SvCUR(sv); + I32 line = 1; while (s && s < send) { - SV *tmpstr = NEWSV(85,0); + const char *t; + SV * const tmpstr = NEWSV(85,0); sv_upgrade(tmpstr, SVt_PVMG); t = strchr(s, '\n'); @@ -2488,28 +2718,18 @@ S_save_lines(pTHX_ AV *array, SV *sv) } } -#ifdef PERL_FLEXIBLE_EXCEPTIONS -STATIC void * -S_docatch_body(pTHX_ va_list args) -{ - return docatch_body(); -} -#endif - -STATIC void * +STATIC void S_docatch_body(pTHX) { CALLRUNOPS(aTHX); - return NULL; + return; } STATIC OP * S_docatch(pTHX_ OP *o) { int ret; - OP *oldop = PL_op; - OP *retop; - volatile PERL_SI *cursi = PL_curstackinfo; + OP * const oldop = PL_op; dJMPENV; #ifdef DEBUGGING @@ -2517,37 +2737,32 @@ S_docatch(pTHX_ OP *o) #endif PL_op = o; - /* Normally, the leavetry at the end of this block of ops will - * pop an op off the return stack and continue there. By setting - * the op to Nullop, we force an exit from the inner runops() - * loop. DAPM. - */ - retop = pop_return(); - push_return(Nullop); - -#ifdef PERL_FLEXIBLE_EXCEPTIONS - redo_body: - CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_docatch_body)); -#else JMPENV_PUSH(ret); -#endif switch (ret) { case 0: -#ifndef PERL_FLEXIBLE_EXCEPTIONS + assert(cxstack_ix >= 0); + assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL); + cxstack[cxstack_ix].blk_eval.cur_top_env = PL_top_env; redo_body: docatch_body(); -#endif break; case 3: /* die caught by an inner eval - continue inner loop */ - if (PL_restartop && cursi == PL_curstackinfo) { + + /* NB XXX we rely on the old popped CxEVAL still being at the top + * of the stack; the way die_where() currently works, this + * assumption is valid. In theory The cur_top_env value should be + * returned in another global, the way retop (aka PL_restartop) + * is. */ + assert(CxTYPE(&cxstack[cxstack_ix+1]) == CXt_EVAL); + + if (PL_restartop + && cxstack[cxstack_ix+1].blk_eval.cur_top_env == PL_top_env) + { PL_op = PL_restartop; PL_restartop = 0; goto redo_body; } - /* a die in this eval - continue in outer loop */ - if (!PL_restartop) - break; /* FALL THROUGH */ default: JMPENV_POP; @@ -2557,19 +2772,19 @@ S_docatch(pTHX_ OP *o) } JMPENV_POP; PL_op = oldop; - return retop; + return Nullop; } OP * -Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) +Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) /* sv Text to convert to OP tree. */ /* startop op_free() this to undo. */ /* code Short string id of the caller. */ { - dSP; /* Make POPBLOCK work. */ + dVAR; dSP; /* Make POPBLOCK work. */ PERL_CONTEXT *cx; SV **newsp; - I32 gimme = 0; /* SUSPECT - INITIALZE TO WHAT? NI-S */ + I32 gimme = G_VOID; I32 optype; OP dummy; OP *rop; @@ -2577,19 +2792,19 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) char *tmpbuf = tbuf; char *safestr; int runtime; - CV* runcv; + CV* runcv = Nullcv; /* initialise to avoid compiler warnings */ ENTER; lex_start(sv); SAVETMPS; /* switch to eval mode */ - if (PL_curcop == &PL_compiling) { + if (IN_PERL_COMPILETIME) { SAVECOPSTASH_FREE(&PL_compiling); CopSTASH_set(&PL_compiling, PL_curstash); } if (PERLDB_NAMEEVAL && CopLINE(PL_curcop)) { - SV *sv = sv_newmortal(); + SV * const sv = sv_newmortal(); Perl_sv_setpvf(aTHX_ sv, "_<(%.10seval %lu)[%s:%"IVdf"]", code, (unsigned long)++PL_evalseq, CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); @@ -2614,17 +2829,16 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) #else SAVEVPTR(PL_op); #endif - PL_hints &= HINT_UTF8; /* we get here either during compilation, or via pp_regcomp at runtime */ - runtime = PL_op && (PL_op->op_type == OP_REGCOMP); + runtime = IN_PERL_RUNTIME; if (runtime) runcv = find_runcv(NULL); PL_op = &dummy; PL_op->op_type = OP_ENTEREVAL; PL_op->op_flags = 0; /* Avoid uninit warning. */ - PUSHBLOCK(cx, CXt_EVAL|(PL_curcop == &PL_compiling ? 0 : CXp_REAL), SP); + PUSHBLOCK(cx, CXt_EVAL|(IN_PERL_COMPILETIME ? 0 : CXp_REAL), SP); PUSHEVAL(cx, 0, Nullgv); if (runtime) @@ -2640,11 +2854,14 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) /* XXX DAPM do this properly one year */ *padp = (AV*)SvREFCNT_inc(PL_comppad); LEAVE; - if (PL_curcop == &PL_compiling) + if (IN_PERL_COMPILETIME) PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); #ifdef OP_IN_REGISTER op = PL_opsave; #endif + PERL_UNUSED_VAR(newsp); + PERL_UNUSED_VAR(optype); + return rop; } @@ -2656,7 +2873,7 @@ Locate the CV corresponding to the currently executing sub or eval. If db_seqp is non_null, skip CVs that are in the DB package and populate *db_seqp with the cop sequence number at the point that the DB:: code was entered. (allows debuggers to eval in the scope of the breakpoint rather -than in in the scope of the debuger itself). +than in the scope of the debugger itself). =cut */ @@ -2664,17 +2881,16 @@ than in in the scope of the debuger itself). CV* Perl_find_runcv(pTHX_ U32 *db_seqp) { - I32 ix; PERL_SI *si; - PERL_CONTEXT *cx; if (db_seqp) *db_seqp = PL_curcop->cop_seq; for (si = PL_curstackinfo; si; si = si->si_prev) { + I32 ix; for (ix = si->si_cxix; ix >= 0; ix--) { - cx = &(si->si_cxstack[ix]); + const PERL_CONTEXT *cx = &(si->si_cxstack[ix]); if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { - CV *cv = cx->blk_sub.cv; + CV * const cv = cx->blk_sub.cv; /* skip DB:: code */ if (db_seqp && PL_debstash && CvSTASH(cv) == PL_debstash) { *db_seqp = cx->blk_oldcop->cop_seq; @@ -2700,8 +2916,8 @@ Perl_find_runcv(pTHX_ U32 *db_seqp) STATIC OP * S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) { - dSP; - OP *saveop = PL_op; + dVAR; dSP; + OP * const saveop = PL_op; PL_in_eval = ((saveop && saveop->op_type == OP_REQUIRE) ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL)) @@ -2746,14 +2962,13 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) if (saveop && saveop->op_flags & OPf_SPECIAL) PL_in_eval |= EVAL_KEEPERR; else - sv_setpv(ERRSV,""); + sv_setpvn(ERRSV,"",0); if (yyparse() || PL_error_count || !PL_eval_root) { - SV **newsp; - I32 gimme; - PERL_CONTEXT *cx; + SV **newsp; /* Used by POPBLOCK. */ + PERL_CONTEXT *cx = &cxstack[cxstack_ix]; I32 optype = 0; /* Might be reset by POPEVAL. */ - STRLEN n_a; - + const char *msg; + PL_op = saveop; if (PL_eval_root) { op_free(PL_eval_root); @@ -2763,29 +2978,30 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) if (!startop) { POPBLOCK(cx,PL_curpm); POPEVAL(cx); - pop_return(); } lex_end(); LEAVE; + + msg = SvPVx_nolen_const(ERRSV); if (optype == OP_REQUIRE) { - char* msg = SvPVx(ERRSV, n_a); + const SV * const nsv = cx->blk_eval.old_namesv; + (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), + &PL_sv_undef, 0); DIE(aTHX_ "%sCompilation failed in require", *msg ? msg : "Unknown error\n"); } else if (startop) { - char* msg = SvPVx(ERRSV, n_a); - POPBLOCK(cx,PL_curpm); POPEVAL(cx); Perl_croak(aTHX_ "%sCompilation failed in regexp", (*msg ? msg : "Unknown error\n")); } else { - char* msg = SvPVx(ERRSV, n_a); if (!*msg) { sv_setpv(ERRSV, "Compilation error"); } } + PERL_UNUSED_VAR(newsp); RETPUSHUNDEF; } CopLINE_set(&PL_compiling, 0); @@ -2793,7 +3009,16 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) *startop = PL_eval_root; } else SAVEFREEOP(PL_eval_root); - if (gimme & G_VOID) + + /* Set the context for this new optree. + * If the last op is an OP_REQUIRE, force scalar context. + * Otherwise, propagate the context from the eval(). */ + if (PL_eval_root->op_type == OP_LEAVEEVAL + && cUNOPx(PL_eval_root)->op_first->op_type == OP_LINESEQ + && cLISTOPx(cUNOPx(PL_eval_root)->op_first)->op_last->op_type + == OP_REQUIRE) + scalar(PL_eval_root); + else if (gimme & G_VOID) scalarvoid(PL_eval_root); else if (gimme & G_ARRAY) list(PL_eval_root); @@ -2804,7 +3029,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) /* Register with debugger: */ if (PERLDB_INTER && saveop->op_type == OP_REQUIRE) { - CV *cv = get_cv("DB::postponed", FALSE); + CV * const cv = get_cv("DB::postponed", FALSE); if (cv) { dSP; PUSHMARK(SP); @@ -2825,20 +3050,21 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) } STATIC PerlIO * -S_doopen_pmc(pTHX_ const char *name, const char *mode) +S_doopen_pm(pTHX_ const char *name, const char *mode) { - STRLEN namelen = strlen(name); +#ifndef PERL_DISABLE_PMC + const STRLEN namelen = strlen(name); PerlIO *fp; if (namelen > 3 && strEQ(name + namelen - 3, ".pm")) { - SV *pmcsv = Perl_newSVpvf(aTHX_ "%s%c", name, 'c'); - char *pmc = SvPV_nolen(pmcsv); - Stat_t pmstat; + SV * const pmcsv = Perl_newSVpvf(aTHX_ "%s%c", name, 'c'); + const char * const pmc = SvPV_nolen_const(pmcsv); Stat_t pmcstat; if (PerlLIO_stat(pmc, &pmcstat) < 0) { fp = PerlIO_open(name, mode); } else { + Stat_t pmstat; if (PerlLIO_stat(name, &pmstat) < 0 || pmstat.st_mtime < pmcstat.st_mtime) { @@ -2854,21 +3080,22 @@ S_doopen_pmc(pTHX_ const char *name, const char *mode) fp = PerlIO_open(name, mode); } return fp; +#else + return PerlIO_open(name, mode); +#endif /* !PERL_DISABLE_PMC */ } PP(pp_require) { - dSP; + dVAR; dSP; register PERL_CONTEXT *cx; SV *sv; - char *name; + const char *name; STRLEN len; - char *tryname = Nullch; + const char *tryname = Nullch; SV *namesv = Nullsv; - SV** svp; - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; PerlIO *tryrsfp = 0; - STRLEN n_a; int filter_has_file = 0; GV *filter_child_proc = 0; SV *filter_state = 0; @@ -2878,81 +3105,46 @@ PP(pp_require) OP *op; sv = POPs; - if (SvNIOKp(sv) && PL_op->op_type != OP_DOFILE) { - if (SvPOK(sv) && SvNOK(sv) && SvNV(sv)) { /* require v5.6.1 */ - UV rev = 0, ver = 0, sver = 0; - STRLEN len; - U8 *s = (U8*)SvPVX(sv); - U8 *end = (U8*)SvPVX(sv) + SvCUR(sv); - if (s < end) { - rev = utf8n_to_uvchr(s, end - s, &len, 0); - s += len; - if (s < end) { - ver = utf8n_to_uvchr(s, end - s, &len, 0); - s += len; - if (s < end) - sver = utf8n_to_uvchr(s, end - s, &len, 0); - } - } - if (PERL_REVISION < rev - || (PERL_REVISION == rev - && (PERL_VERSION < ver - || (PERL_VERSION == ver - && PERL_SUBVERSION < sver)))) - { - DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required--this is only " - "v%d.%d.%d, stopped", rev, ver, sver, PERL_REVISION, - PERL_VERSION, PERL_SUBVERSION); - } - if (ckWARN(WARN_PORTABLE)) + if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) { + if ( SvVOK(sv) && ckWARN(WARN_PORTABLE) ) /* require v5.6.1 */ Perl_warner(aTHX_ packWARN(WARN_PORTABLE), "v-string in use/require non-portable"); - RETPUSHYES; + + sv = new_version(sv); + if (!sv_derived_from(PL_patchlevel, "version")) + (void *)upg_version(PL_patchlevel); + if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) { + if ( vcmp(sv,PL_patchlevel) < 0 ) + DIE(aTHX_ "Perls since %"SVf" too modern--this is %"SVf", stopped", + vnormal(sv), vnormal(PL_patchlevel)); } - else if (!SvPOKp(sv)) { /* require 5.005_03 */ - if ((NV)PERL_REVISION + ((NV)PERL_VERSION/(NV)1000) - + ((NV)PERL_SUBVERSION/(NV)1000000) - + 0.00000099 < SvNV(sv)) - { - NV nrev = SvNV(sv); - UV rev = (UV)nrev; - NV nver = (nrev - rev) * 1000; - UV ver = (UV)(nver + 0.0009); - NV nsver = (nver - ver) * 1000; - UV sver = (UV)(nsver + 0.0009); - - /* help out with the "use 5.6" confusion */ - if (sver == 0 && (rev > 5 || (rev == 5 && ver >= 100))) { - DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required" - " (did you mean v%"UVuf".%03"UVuf"?)--" - "this is only v%d.%d.%d, stopped", - rev, ver, sver, rev, ver/100, - PERL_REVISION, PERL_VERSION, PERL_SUBVERSION); - } - else { - DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required--" - "this is only v%d.%d.%d, stopped", - rev, ver, sver, PERL_REVISION, PERL_VERSION, - PERL_SUBVERSION); - } - } - RETPUSHYES; + else { + if ( vcmp(sv,PL_patchlevel) > 0 ) + DIE(aTHX_ "Perl %"SVf" required--this is only %"SVf", stopped", + vnormal(sv), vnormal(PL_patchlevel)); } + + RETPUSHYES; } - name = SvPV(sv, len); + name = SvPV_const(sv, len); if (!(name && len > 0 && *name)) DIE(aTHX_ "Null filename used"); TAINT_PROPER("require"); - if (PL_op->op_type == OP_REQUIRE && - (svp = hv_fetch(GvHVn(PL_incgv), name, len, 0)) && - *svp != &PL_sv_undef) - RETPUSHYES; + if (PL_op->op_type == OP_REQUIRE) { + SV ** const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0); + if ( svp ) { + if (*svp != &PL_sv_undef) + RETPUSHYES; + else + DIE(aTHX_ "Compilation failed in require"); + } + } /* prepare to compile file */ if (path_is_absolute(name)) { tryname = name; - tryrsfp = doopen_pmc(name,PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(name,PERL_SCRIPT_MODE); } #ifdef MACOS_TRADITIONAL if (!tryrsfp) { @@ -2961,12 +3153,12 @@ PP(pp_require) MacPerl_CanonDir(name, newname, 1); if (path_is_absolute(newname)) { tryname = newname; - tryrsfp = doopen_pmc(newname,PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(newname,PERL_SCRIPT_MODE); } } #endif if (!tryrsfp) { - AV *ar = GvAVn(PL_incgv); + AV * const ar = GvAVn(PL_incgv); I32 i; #ifdef VMS char *unixname; @@ -2989,7 +3181,7 @@ PP(pp_require) Perl_sv_setpvf(aTHX_ namesv, "/loader/0x%"UVxf"/%s", PTR2UV(SvRV(dirsv)), name); - tryname = SvPVX(namesv); + tryname = SvPVX_const(namesv); tryrsfp = 0; ENTER; @@ -3062,6 +3254,7 @@ PP(pp_require) PERL_SCRIPT_MODE); } } + SP--; } PUTBACK; @@ -3096,7 +3289,7 @@ PP(pp_require) || (*name == ':' && name[1] != ':' && strchr(name+2, ':')) #endif ) { - char *dir = SvPVx(dirsv, n_a); + const char *dir = SvPVx_nolen_const(dirsv); #ifdef MACOS_TRADITIONAL char buf1[256]; char buf2[256]; @@ -3104,19 +3297,33 @@ PP(pp_require) MacPerl_CanonDir(name, buf2, 1); Perl_sv_setpvf(aTHX_ namesv, "%s%s", MacPerl_CanonDir(dir, buf1, 0), buf2+(buf2[0] == ':')); #else -#ifdef VMS +# ifdef VMS char *unixdir; if ((unixdir = tounixpath(dir, Nullch)) == Nullch) continue; sv_setpv(namesv, unixdir); sv_catpv(namesv, unixname); -#else +# else +# ifdef __SYMBIAN32__ + if (PL_origfilename[0] && + PL_origfilename[1] == ':' && + !(dir[0] && dir[1] == ':')) + Perl_sv_setpvf(aTHX_ namesv, + "%c:%s\\%s", + PL_origfilename[0], + dir, name); + else + Perl_sv_setpvf(aTHX_ namesv, + "%s\\%s", + dir, name); +# else Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name); -#endif +# endif +# endif #endif TAINT_PROPER("require"); - tryname = SvPVX(namesv); - tryrsfp = doopen_pmc(tryname, PERL_SCRIPT_MODE); + tryname = SvPVX_const(namesv); + tryrsfp = doopen_pm(tryname, PERL_SCRIPT_MODE); if (tryrsfp) { if (tryname[0] == '.' && tryname[1] == '/') tryname += 2; @@ -3132,26 +3339,33 @@ PP(pp_require) SvREFCNT_dec(namesv); if (!tryrsfp) { if (PL_op->op_type == OP_REQUIRE) { - char *msgstr = name; - if (namesv) { /* did we lookup @INC? */ - SV *msg = sv_2mortal(newSVpv(msgstr,0)); - SV *dirmsgsv = NEWSV(0, 0); - AV *ar = GvAVn(PL_incgv); - I32 i; - sv_catpvn(msg, " in @INC", 8); - if (instr(SvPVX(msg), ".h ")) - sv_catpv(msg, " (change .h to .ph maybe?)"); - if (instr(SvPVX(msg), ".ph ")) - sv_catpv(msg, " (did you run h2ph?)"); - sv_catpv(msg, " (@INC contains:"); - for (i = 0; i <= AvFILL(ar); i++) { - char *dir = SvPVx(*av_fetch(ar, i, TRUE), n_a); - Perl_sv_setpvf(aTHX_ dirmsgsv, " %s", dir); - sv_catsv(msg, dirmsgsv); - } - sv_catpvn(msg, ")", 1); - SvREFCNT_dec(dirmsgsv); - msgstr = SvPV_nolen(msg); + const char *msgstr = name; + if(errno == EMFILE) { + SV * const msg = sv_2mortal(newSVpv(msgstr,0)); + sv_catpv(msg, ": "); + sv_catpv(msg, Strerror(errno)); + msgstr = SvPV_nolen_const(msg); + } else { + if (namesv) { /* did we lookup @INC? */ + SV * const msg = sv_2mortal(newSVpv(msgstr,0)); + SV * const dirmsgsv = NEWSV(0, 0); + AV * const ar = GvAVn(PL_incgv); + I32 i; + sv_catpvn(msg, " in @INC", 8); + if (instr(SvPVX_const(msg), ".h ")) + sv_catpv(msg, " (change .h to .ph maybe?)"); + if (instr(SvPVX_const(msg), ".ph ")) + sv_catpv(msg, " (did you run h2ph?)"); + sv_catpv(msg, " (@INC contains:"); + for (i = 0; i <= AvFILL(ar); i++) { + const char *dir = SvPVx_nolen_const(*av_fetch(ar, i, TRUE)); + Perl_sv_setpvf(aTHX_ dirmsgsv, " %s", dir); + sv_catsv(msg, dirmsgsv); + } + sv_catpvn(msg, ")", 1); + SvREFCNT_dec(dirmsgsv); + msgstr = SvPV_nolen_const(msg); + } } DIE(aTHX_ "Can't locate %s", msgstr); } @@ -3164,11 +3378,12 @@ PP(pp_require) /* Assume success here to prevent recursive requirement. */ len = strlen(name); /* Check whether a hook in @INC has already filled %INC */ - if (!hook_sv || !(svp = hv_fetch(GvHVn(PL_incgv), name, len, 0))) { - (void)hv_store(GvHVn(PL_incgv), name, len, - (hook_sv ? SvREFCNT_inc(hook_sv) - : newSVpv(CopFILE(&PL_compiling), 0)), - 0 ); + if (!hook_sv) { + (void)hv_store(GvHVn(PL_incgv), name, len, newSVpv(CopFILE(&PL_compiling),0),0); + } else { + SV** const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0); + if (!svp) + (void)hv_store(GvHVn(PL_incgv), name, len, SvREFCNT_inc(hook_sv), 0 ); } ENTER; @@ -3193,7 +3408,7 @@ PP(pp_require) PL_compiling.cop_io = Nullsv; if (filter_sub || filter_child_proc) { - SV *datasv = filter_add(run_user_filter, Nullsv); + SV * const datasv = filter_add(run_user_filter, Nullsv); IoLINES(datasv) = filter_has_file; IoFMT_GV(datasv) = (GV *)filter_child_proc; IoTOP_GV(datasv) = (GV *)filter_state; @@ -3201,9 +3416,9 @@ PP(pp_require) } /* switch to eval mode */ - push_return(PL_op->op_next); PUSHBLOCK(cx, CXt_EVAL, SP); PUSHEVAL(cx, name, Nullgv); + cx->blk_eval.retop = PL_op->op_next; SAVECOPLINE(&PL_compiling); CopLINE_set(&PL_compiling, 0); @@ -3215,7 +3430,7 @@ PP(pp_require) PL_encoding = Nullsv; op = DOCATCH(doeval(gimme, NULL, Nullcv, PL_curcop->cop_seq)); - + /* Restore encoding. */ PL_encoding = encoding; @@ -3229,10 +3444,11 @@ PP(pp_dofile) PP(pp_entereval) { - dSP; + dVAR; dSP; register PERL_CONTEXT *cx; dPOPss; - I32 gimme = GIMME_V, was = PL_sub_generation; + const I32 gimme = GIMME_V; + const I32 was = PL_sub_generation; char tbuf[TYPE_DIGITS(long) + 12]; char *tmpbuf = tbuf; char *safestr; @@ -3241,7 +3457,7 @@ PP(pp_entereval) CV* runcv; U32 seq; - if (!SvPV(sv,len)) + if (!SvPV_const(sv,len)) RETPUSHUNDEF; TAINT_PROPER("eval"); @@ -3252,7 +3468,7 @@ PP(pp_entereval) /* switch to eval mode */ if (PERLDB_NAMEEVAL && CopLINE(PL_curcop)) { - SV *sv = sv_newmortal(); + SV * const sv = sv_newmortal(); Perl_sv_setpvf(aTHX_ sv, "_<(eval %lu)[%s:%"IVdf"]", (unsigned long)++PL_evalseq, CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); @@ -3294,9 +3510,9 @@ PP(pp_entereval) * to do the dirty work for us */ runcv = find_runcv(&seq); - push_return(PL_op->op_next); PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP); PUSHEVAL(cx, 0, Nullgv); + cx->blk_eval.retop = PL_op->op_next; /* prepare to compile string */ @@ -3313,19 +3529,19 @@ PP(pp_entereval) PP(pp_leaveeval) { - dSP; + dVAR; dSP; register SV **mark; SV **newsp; PMOP *newpm; I32 gimme; register PERL_CONTEXT *cx; OP *retop; - U8 save_flags = PL_op -> op_flags; + const U8 save_flags = PL_op -> op_flags; I32 optype; POPBLOCK(cx,newpm); POPEVAL(cx); - retop = pop_return(); + retop = cx->blk_eval.retop; TAINT_NOT; if (gimme == G_VOID) @@ -3365,15 +3581,15 @@ PP(pp_leaveeval) !(gimme == G_SCALAR ? SvTRUE(*SP) : SP > newsp)) { /* Unassume the success we assumed earlier. */ - SV *nsv = cx->blk_eval.old_namesv; - (void)hv_delete(GvHVn(PL_incgv), SvPVX(nsv), SvCUR(nsv), G_DISCARD); - retop = Perl_die(aTHX_ "%s did not return a true value", SvPVX(nsv)); + SV * const nsv = cx->blk_eval.old_namesv; + (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD); + retop = Perl_die(aTHX_ "%"SVf" did not return a true value", nsv); /* die_where() did LEAVE, or we won't be here */ } else { LEAVE; if (!(save_flags & OPf_SPECIAL)) - sv_setpv(ERRSV,""); + sv_setpvn(ERRSV,"",0); } RETURNOP(retop); @@ -3381,37 +3597,36 @@ PP(pp_leaveeval) PP(pp_entertry) { - dSP; + dVAR; dSP; register PERL_CONTEXT *cx; - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; ENTER; SAVETMPS; - push_return(cLOGOP->op_other->op_next); PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), SP); PUSHEVAL(cx, 0, 0); + cx->blk_eval.retop = cLOGOP->op_other->op_next; PL_in_eval = EVAL_INEVAL; - sv_setpv(ERRSV,""); + sv_setpvn(ERRSV,"",0); PUTBACK; return DOCATCH(PL_op->op_next); } PP(pp_leavetry) { - dSP; + dVAR; dSP; register SV **mark; SV **newsp; PMOP *newpm; - OP* retop; I32 gimme; register PERL_CONTEXT *cx; I32 optype; POPBLOCK(cx,newpm); POPEVAL(cx); - retop = pop_return(); + PERL_UNUSED_VAR(optype); TAINT_NOT; if (gimme == G_VOID) @@ -3442,11 +3657,11 @@ PP(pp_leavetry) PL_curpm = newpm; /* Don't pop $1 et al till now */ LEAVE; - sv_setpv(ERRSV,""); - RETURNOP(retop); + sv_setpvn(ERRSV,"",0); + RETURN; } -STATIC void +STATIC OP * S_doparseform(pTHX_ SV *sv) { STRLEN len; @@ -3457,16 +3672,26 @@ S_doparseform(pTHX_ SV *sv) bool noblank = FALSE; bool repeat = FALSE; bool postspace = FALSE; - U16 *fops; - register U16 *fpc; - U16 *linepc = 0; + U32 *fops; + register U32 *fpc; + U32 *linepc = 0; register I32 arg; bool ischop; + bool unchopnum = FALSE; + int maxops = 12; /* FF_LINEMARK + FF_END + 10 (\0 without preceding \n) */ if (len == 0) Perl_croak(aTHX_ "Null picture in formline"); - New(804, fops, (send - s)*3+10, U16); /* Almost certainly too long... */ + /* estimate the buffer size needed */ + for (base = s; s <= send; s++) { + if (*s == '\n' || *s == '@' || *s == '^') + maxops += 10; + } + s = base; + base = Nullch; + + Newx(fops, maxops, U32); fpc = fops; if (s < send) { @@ -3493,8 +3718,12 @@ S_doparseform(pTHX_ SV *sv) case ' ': case '\t': skipspaces++; continue; - - case '\n': case 0: + case 0: + if (s < send) { + skipspaces = 0; + continue; + } /* else FALL THROUGH */ + case '\n': arg = s - base; skipspaces++; arg -= skipspaces; @@ -3550,8 +3779,12 @@ S_doparseform(pTHX_ SV *sv) *fpc++ = FF_FETCH; if (*s == '*') { s++; - *fpc++ = 0; - *fpc++ = FF_LINEGLOB; + *fpc++ = 2; /* skip the @* or ^* */ + if (ischop) { + *fpc++ = FF_LINESNGL; + *fpc++ = FF_CHOP; + } else + *fpc++ = FF_LINEGLOB; } else if (*s == '#' || (*s == '.' && s[1] == '#')) { arg = ischop ? 512 : 0; @@ -3559,9 +3792,7 @@ S_doparseform(pTHX_ SV *sv) while (*s == '#') s++; if (*s == '.') { - char *f; - s++; - f = s; + const char * const f = ++s; while (*s == '#') s++; arg |= 256 + (s - f); @@ -3569,6 +3800,7 @@ S_doparseform(pTHX_ SV *sv) *fpc++ = s - base; /* fieldsize for FETCH */ *fpc++ = FF_DECIMAL; *fpc++ = (U16)arg; + unchopnum |= ! ischop; } else if (*s == '0' && s[1] == '#') { /* Zero padded decimals */ arg = ischop ? 512 : 0; @@ -3577,9 +3809,7 @@ S_doparseform(pTHX_ SV *sv) while (*s == '#') s++; if (*s == '.') { - char *f; - s++; - f = s; + const char * const f = ++s; while (*s == '#') s++; arg |= 256 + (s - f); @@ -3587,6 +3817,7 @@ S_doparseform(pTHX_ SV *sv) *fpc++ = s - base; /* fieldsize for FETCH */ *fpc++ = FF_0DECIMAL; *fpc++ = (U16)arg; + unchopnum |= ! ischop; } else { I32 prespace = 0; @@ -3629,24 +3860,58 @@ S_doparseform(pTHX_ SV *sv) } *fpc++ = FF_END; + assert (fpc <= fops + maxops); /* ensure our buffer estimate was valid */ arg = fpc - fops; { /* need to jump to the next word */ int z; z = WORD_ALIGN - SvCUR(sv) % WORD_ALIGN; - SvGROW(sv, SvCUR(sv) + z + arg * sizeof(U16) + 4); + SvGROW(sv, SvCUR(sv) + z + arg * sizeof(U32) + 4); s = SvPVX(sv) + SvCUR(sv) + z; } - Copy(fops, s, arg, U16); + Copy(fops, s, arg, U32); Safefree(fops); sv_magic(sv, Nullsv, PERL_MAGIC_fm, Nullch, 0); SvCOMPILED_on(sv); + + if (unchopnum && repeat) + DIE(aTHX_ "Repeated format line will never terminate (~~ and @#)"); + return 0; +} + + +STATIC bool +S_num_overflow(NV value, I32 fldsize, I32 frcsize) +{ + /* Can value be printed in fldsize chars, using %*.*f ? */ + NV pwr = 1; + NV eps = 0.5; + bool res = FALSE; + int intsize = fldsize - (value < 0 ? 1 : 0); + + if (frcsize & 256) + intsize--; + frcsize &= 255; + intsize -= frcsize; + + while (intsize--) pwr *= 10.0; + while (frcsize--) eps /= 10.0; + + if( value >= 0 ){ + if (value + eps >= pwr) + res = TRUE; + } else { + if (value - eps <= -pwr) + res = TRUE; + } + return res; } static I32 run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) { + dVAR; SV *datasv = FILTER_DATA(idx); - int filter_has_file = IoLINES(datasv); + const int filter_has_file = IoLINES(datasv); GV *filter_child_proc = (GV *)IoFMT_GV(datasv); SV *filter_state = (SV *)IoTOP_GV(datasv); SV *filter_sub = (SV *)IoBOTTOM_GV(datasv); @@ -3715,7 +3980,7 @@ run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) /* perhaps someone can come up with a better name for this? it is not really "absolute", per se ... */ static bool -S_path_is_absolute(pTHX_ char *name) +S_path_is_absolute(pTHX_ const char *name) { if (PERL_FILE_IS_ABSOLUTE(name) #ifdef MACOS_TRADITIONAL @@ -3730,3 +3995,13 @@ S_path_is_absolute(pTHX_ char *name) else return FALSE; } + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * ex: set ts=8 sts=4 sw=4 noet: + */