X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/51d9a56bf5df931c436b7ede535c78bc64655187..59f00321bbc2d04656a65e0e9ccbbd93a8708e71:/pp_ctl.c diff --git a/pp_ctl.c b/pp_ctl.c index ac33adf..42d63c6 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1,6 +1,7 @@ /* pp_ctl.c * - * Copyright (c) 1991-2003, Larry Wall + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + * 2000, 2001, 2002, 2003, 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. @@ -21,7 +22,7 @@ #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 +59,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; } @@ -97,7 +99,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) @@ -157,6 +159,12 @@ PP(pp_substcont) char *orig = cx->sb_orig; register REGEXP *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); RX_MATCH_UTF8_set(rx, SvUTF8(cx->sb_targ)); @@ -212,6 +220,7 @@ PP(pp_substcont) SvTAINT(targ); LEAVE_SCOPE(cx->sb_oldsave); + ReREFCNT_dec(rx); POPSUBST(cx); RETURNOP(pm->op_next); } @@ -247,6 +256,8 @@ PP(pp_substcont) sv_pos_b2u(sv, &i); mg->mg_len = i; } + if (old != rx) + ReREFCNT_inc(rx); cx->sb_rxtainted |= RX_MATCH_TAINTED(rx); rxres_save(&cx->sb_rxres, rx); RETURNOP(pm->op_pmreplstart); @@ -337,7 +348,7 @@ PP(pp_formline) { dSP; dMARK; dORIGMARK; register SV *tmpForm = *++MARK; - register U16 *fpc; + register U32 *fpc; register char *t; register char *f; register char *s; @@ -358,15 +369,20 @@ PP(pp_formline) bool item_is_utf8 = FALSE; bool targ_is_utf8 = FALSE; SV * nsv = Nullsv; + OP * parseres = 0; + 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)) @@ -377,7 +393,7 @@ PP(pp_formline) /* need to jump to the next word */ s = f + len + WORD_ALIGN - SvCUR(tmpForm) % WORD_ALIGN; - fpc = (U16*)s; + fpc = (U32*)s; for (;;) { DEBUG_f( { @@ -402,6 +418,7 @@ PP(pp_formline) case FF_LINEMARK: name = "LINEMARK"; break; case FF_END: name = "END"; 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); @@ -508,6 +525,7 @@ PP(pp_formline) while (s < send) { if (*s == '\r') { itemsize = s - item; + chophere = s; break; } if (*s++ & ~31) @@ -547,6 +565,7 @@ PP(pp_formline) while (s < send) { if (*s == '\r') { itemsize = s - item; + chophere = s; break; } if (*s++ & ~31) @@ -637,7 +656,7 @@ PP(pp_formline) sv_catpvn_utf8_upgrade(PL_formtarget, s, arg, nsv); for (; t < SvEND(PL_formtarget); t++) { #ifdef EBCDIC - int ch = *t++ = *s++; + int ch = *t; if (iscntrl(ch)) #else if (!(*t & ~31)) @@ -664,9 +683,16 @@ PP(pp_formline) s++; } sv_chop(sv,s); + SvSETMAGIC(sv); break; + case FF_LINESNGL: + chopspace = 0; + oneline = TRUE; + goto ff_line; case FF_LINEGLOB: + oneline = FALSE; + ff_line: item = s = SvPV(sv, len); itemsize = len; if ((item_is_utf8 = DO_UTF8(sv))) @@ -675,20 +701,31 @@ PP(pp_formline) bool chopped = FALSE; gotsome = TRUE; send = s + len; + chophere = s + itemsize; while (s < send) { if (*s++ == '\n') { - if (s == send) { - itemsize--; + if (oneline) { chopped = TRUE; + chophere = s; + break; + } else { + if (s == send) { + itemsize--; + chopped = TRUE; + } else + lines++; } - else - lines++; } } SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget)); if (targ_is_utf8) SvUTF8_on(PL_formtarget); - sv_catsv(PL_formtarget, sv); + 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); @@ -698,46 +735,24 @@ PP(pp_formline) } 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--) @@ -746,31 +761,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 == ' ') ; @@ -857,14 +863,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) @@ -880,6 +891,7 @@ PP(pp_mapstart) PP(pp_mapwhile) { dSP; + I32 gimme = GIMME_V; I32 items = (SP - PL_stack_base) - *PL_markstack_ptr; /* how many new items */ I32 count; I32 shift; @@ -890,7 +902,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 @@ -934,7 +946,6 @@ PP(pp_mapwhile) /* All done yet? */ if (PL_markstack_ptr[-1] > *PL_markstack_ptr) { - I32 gimme = GIMME_V; (void)POPMARK; /* pop top */ LEAVE; /* exit outer scope */ @@ -959,7 +970,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); } @@ -1019,6 +1033,16 @@ PP(pp_flip) } } +/* 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)) || \ + (looks_like_number(left) && SvPOKp(left) && *SvPVX(left) != '0' && \ + looks_like_number(right))) + PP(pp_flop) { dSP; @@ -1034,15 +1058,7 @@ PP(pp_flop) 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 (RANGE_IS_NUMERIC(left,right)) { if (SvNV(left) < IV_MIN || SvNV(right) > IV_MAX) DIE(aTHX_ "Range iterator outside integer range"); i = SvIV(left); @@ -1317,8 +1333,6 @@ OP * Perl_die_where(pTHX_ char *message, STRLEN msglen) { STRLEN n_a; - IO *io; - MAGIC *mg; if (PL_in_eval) { I32 cxix; @@ -1353,8 +1367,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) @@ -1371,6 +1383,8 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) POPBLOCK(cx,PL_curpm); if (CxTYPE(cx) != CXt_EVAL) { + if (!message) + message = SvPVx(ERRSV, msglen); PerlIO_write(Perl_error_log, "panic: die ", 11); PerlIO_write(Perl_error_log, message, msglen); my_exit(1); @@ -1391,6 +1405,9 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) if (optype == OP_REQUIRE) { char* msg = SvPVx(ERRSV, n_a); + SV *nsv = cx->blk_eval.old_namesv; + (void)hv_store(GvHVn(PL_incgv), SvPVX(nsv), SvCUR(nsv), + &PL_sv_undef, 0); DIE(aTHX_ "%sCompilation failed in require", *msg ? msg : "Unknown error\n"); } @@ -1400,30 +1417,7 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen) 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; - - 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; @@ -1715,7 +1709,6 @@ PP(pp_dbstate) PUSHBLOCK(cx, CXt_SUB, SP); PUSHSUB_DB(cx); CvDEPTH(cv)++; - (void)SvREFCNT_inc(cv); PAD_SET_CUR(CvPADLIST(cv),1); RETURNOP(CvSTART(cv)); } @@ -1743,6 +1736,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); @@ -1774,12 +1772,7 @@ 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 (RANGE_IS_NUMERIC(sv,(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"); @@ -1890,6 +1883,7 @@ PP(pp_return) switch (CxTYPE(cx)) { case CXt_SUB: popsub2 = TRUE; + cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */ break; case CXt_EVAL: if (!(PL_in_eval & EVAL_KEEPERR)) @@ -1952,6 +1946,7 @@ PP(pp_return) LEAVE; /* Stack values are safe: */ if (popsub2) { + cxstack_ix--; POPSUB(cx,sv); /* release CV and @_ ... */ } else @@ -1992,6 +1987,7 @@ PP(pp_last) dounwind(cxix); POPBLOCK(cx,newpm); + cxstack_ix++; /* temporarily protect top context */ mark = newsp; switch (CxTYPE(cx)) { case CXt_LOOP: @@ -2034,6 +2030,7 @@ PP(pp_last) PUTBACK; LEAVE; + cxstack_ix--; /* Stack values are safe: */ switch (pop2) { case CXt_LOOP: @@ -2233,6 +2230,8 @@ PP(pp_goto) AvFLAGS(av) = AVf_REIFY; PAD_SVl(0) = (SV*)(cx->blk_sub.argarray = av); } + else + CLEAR_ARGARRAY(av); } else if (CvXSUB(cv)) { /* put GvAV(defgv) back onto stack */ AV* av; @@ -2345,7 +2344,10 @@ PP(pp_goto) CV *gotocv; if (PERLDB_SUB_NN) { - SvIVX(sv) = PTR2IV(cv); /* Already upgraded, saved */ + (void)SvUPGRADE(sv, SVt_PVIV); + (void)SvIOK_on(sv); + SAVEIV(SvIVX(sv)); + SvIVX(sv) = PTR2IV(cv); /* Do it the quickest way */ } else { save_item(sv); gv_efullname3(sv, CvGV(cv), Nullch); @@ -2388,7 +2390,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); @@ -2675,7 +2677,7 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) SAVETMPS; /* switch to eval mode */ - if (PL_curcop == &PL_compiling) { + if (IN_PERL_COMPILETIME) { SAVECOPSTASH_FREE(&PL_compiling); CopSTASH_set(&PL_compiling, PL_curstash); } @@ -2708,14 +2710,14 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp) 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) @@ -2731,7 +2733,7 @@ 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; @@ -2839,9 +2841,8 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) else sv_setpv(ERRSV,""); 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; @@ -2860,6 +2861,9 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) LEAVE; if (optype == OP_REQUIRE) { char* msg = SvPVx(ERRSV, n_a); + SV *nsv = cx->blk_eval.old_namesv; + (void)hv_store(GvHVn(PL_incgv), SvPVX(nsv), SvCUR(nsv), + &PL_sv_undef, 0); DIE(aTHX_ "%sCompilation failed in require", *msg ? msg : "Unknown error\n"); } @@ -2884,7 +2888,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); @@ -2916,8 +2929,9 @@ 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) { +#ifndef PERL_DISABLE_PMC STRLEN namelen = strlen(name); PerlIO *fp; @@ -2945,6 +2959,9 @@ 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) @@ -3035,15 +3052,18 @@ PP(pp_require) 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; + (svp = hv_fetch(GvHVn(PL_incgv), name, len, 0))) { + 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) { @@ -3052,7 +3072,7 @@ 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 @@ -3153,6 +3173,7 @@ PP(pp_require) PERL_SCRIPT_MODE); } } + SP--; } PUTBACK; @@ -3207,7 +3228,7 @@ PP(pp_require) #endif TAINT_PROPER("require"); tryname = SvPVX(namesv); - tryrsfp = doopen_pmc(tryname, PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(tryname, PERL_SCRIPT_MODE); if (tryrsfp) { if (tryname[0] == '.' && tryname[1] == '/') tryname += 2; @@ -3537,7 +3558,7 @@ PP(pp_leavetry) RETURNOP(retop); } -STATIC void +STATIC OP * S_doparseform(pTHX_ SV *sv) { STRLEN len; @@ -3548,16 +3569,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; + + New(804, fops, maxops, U32); fpc = fops; if (s < send) { @@ -3584,8 +3615,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; @@ -3641,8 +3676,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; @@ -3660,6 +3699,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; @@ -3678,6 +3718,7 @@ S_doparseform(pTHX_ SV *sv) *fpc++ = s - base; /* fieldsize for FETCH */ *fpc++ = FF_0DECIMAL; *fpc++ = (U16)arg; + unchopnum |= ! ischop; } else { I32 prespace = 0; @@ -3720,17 +3761,50 @@ 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