X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_ctl.c;h=54524ae6774770286c9b9d709748923be46c7c66;hb=1304aa9d125296870a384c81cea5102c45d467c8;hp=d51569d224a865ca924a604efbe64d75156bac18;hpb=22921e25517d6c195d0fab9eb946bfafb563c256;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_ctl.c b/pp_ctl.c index d51569d..54524ae 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -27,7 +27,7 @@ static OP *docatch _((OP *o)); static OP *doeval _((int gimme)); -static OP *dofindlabel _((OP *op, char *label, OP **opstack)); +static OP *dofindlabel _((OP *o, char *label, OP **opstack, OP **oplimit)); static void doparseform _((SV *sv)); static I32 dopoptoeval _((I32 startingblock)); static I32 dopoptolabel _((char *label)); @@ -94,7 +94,7 @@ PP(pp_regcomp) { pm->op_pmflags |= PMf_WHITE; if (pm->op_pmflags & PMf_KEEP) { - pm->op_pmflags &= ~PMf_RUNTIME; /* no point compiling again */ + pm->op_private &= ~OPpRUNTIME; /* no point compiling again */ hoistmust(pm); cLOGOP->op_first->op_next = op->op_next; } @@ -112,6 +112,8 @@ PP(pp_substcont) char *orig = cx->sb_orig; register REGEXP *rx = cx->sb_rx; + rxres_restore(&cx->sb_rxres, rx); + if (cx->sb_iters++) { if (cx->sb_iters > cx->sb_maxiters) DIE("Substitution loop"); @@ -119,9 +121,6 @@ PP(pp_substcont) if (!cx->sb_rxtainted) cx->sb_rxtainted = SvTAINTED(TOPs); sv_catsv(dstr, POPs); - if (rx->subbase) - Safefree(rx->subbase); - rx->subbase = cx->sb_subbase; /* Are we done */ if (cx->sb_once || !pregexec(rx, s, cx->sb_strend, orig, @@ -139,10 +138,10 @@ PP(pp_substcont) SvLEN_set(targ, SvLEN(dstr)); SvPVX(dstr) = 0; sv_free(dstr); - (void)SvPOK_only(targ); SvSETMAGIC(targ); SvTAINT(targ); + PUSHs(sv_2mortal(newSViv((I32)cx->sb_iters - 1))); LEAVE_SCOPE(cx->sb_oldsave); POPSUBST(cx); @@ -159,13 +158,76 @@ PP(pp_substcont) cx->sb_m = m = rx->startp[0]; sv_catpvn(dstr, s, m-s); cx->sb_s = rx->endp[0]; - cx->sb_subbase = rx->subbase; cx->sb_rxtainted |= rx->exec_tainted; - - rx->subbase = Nullch; /* so recursion works */ + rxres_save(&cx->sb_rxres, rx); RETURNOP(pm->op_pmreplstart); } +void +rxres_save(rsp, rx) +void **rsp; +REGEXP *rx; +{ + UV *p = (UV*)*rsp; + U32 i; + + if (!p || p[1] < rx->nparens) { + i = 6 + rx->nparens * 2; + if (!p) + New(501, p, i, UV); + else + Renew(p, i, UV); + *rsp = (void*)p; + } + + *p++ = (UV)rx->subbase; + rx->subbase = Nullch; + + *p++ = rx->nparens; + + *p++ = (UV)rx->subbeg; + *p++ = (UV)rx->subend; + for (i = 0; i <= rx->nparens; ++i) { + *p++ = (UV)rx->startp[i]; + *p++ = (UV)rx->endp[i]; + } +} + +void +rxres_restore(rsp, rx) +void **rsp; +REGEXP *rx; +{ + UV *p = (UV*)*rsp; + U32 i; + + Safefree(rx->subbase); + rx->subbase = (char*)(*p); + *p++ = 0; + + rx->nparens = *p++; + + rx->subbeg = (char*)(*p++); + rx->subend = (char*)(*p++); + for (i = 0; i <= rx->nparens; ++i) { + rx->startp[i] = (char*)(*p++); + rx->endp[i] = (char*)(*p++); + } +} + +void +rxres_free(rsp) +void **rsp; +{ + UV *p = (UV*)*rsp; + + if (p) { + Safefree((char*)(*p)); + Safefree(p); + *rsp = Null(void*); + } +} + PP(pp_formline) { dSP; dMARK; dORIGMARK; @@ -471,8 +533,8 @@ PP(pp_grepstart) RETURNOP(op->op_next->op_next); } stack_sp = stack_base + *markstack_ptr + 1; - pp_pushmark(); /* push dst */ - pp_pushmark(); /* push src */ + pp_pushmark(ARGS); /* push dst */ + pp_pushmark(ARGS); /* push src */ ENTER; /* enter outer scope */ SAVETMPS; @@ -487,7 +549,7 @@ PP(pp_grepstart) PUTBACK; if (op->op_type == OP_MAPSTART) - pp_pushmark(); /* push top */ + pp_pushmark(ARGS); /* push top */ return ((LOGOP*)op->op_next)->op_other; } @@ -607,7 +669,7 @@ PP(pp_sort) sortcop = CvSTART(cv); SAVESPTR(CvROOT(cv)->op_ppaddr); CvROOT(cv)->op_ppaddr = ppaddr[OP_NULL]; - + SAVESPTR(curpad); curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]); } @@ -636,7 +698,7 @@ PP(pp_sort) bool oldcatch = CATCH_GET; SAVETMPS; - SAVESPTR(op); + SAVEOP(); oldstack = curstack; if (!sortstack) { @@ -654,7 +716,16 @@ PP(pp_sort) SAVESPTR(GvSV(firstgv)); SAVESPTR(GvSV(secondgv)); + PUSHBLOCK(cx, CXt_NULL, stack_base); + if (!(op->op_flags & OPf_SPECIAL)) { + bool hasargs = FALSE; + cx->cx_type = CXt_SUB; + cx->blk_gimme = G_SCALAR; + PUSHSUB(cx); + if (!CvDEPTH(cv)) + SvREFCNT_inc(cv); /* in preparation for POPSUB */ + } sortcxix = cxstack_ix; qsort((char*)(myorigmark+1), max, sizeof(SV*), sortcv); @@ -778,6 +849,7 @@ static I32 dopoptolabel(label) char *label; { + dTHR; register I32 i; register CONTEXT *cx; @@ -824,11 +896,12 @@ dowantarray() I32 block_gimme() { + dTHR; I32 cxix; cxix = dopoptosub(cxstack_ix); if (cxix < 0) - return G_SCALAR; + return G_VOID; switch (cxstack[cxix].blk_gimme) { case G_VOID: @@ -846,6 +919,7 @@ static I32 dopoptosub(startingblock) I32 startingblock; { + dTHR; I32 i; register CONTEXT *cx; for (i = startingblock; i >= 0; i--) { @@ -866,6 +940,7 @@ static I32 dopoptoeval(startingblock) I32 startingblock; { + dTHR; I32 i; register CONTEXT *cx; for (i = startingblock; i >= 0; i--) { @@ -885,6 +960,7 @@ static I32 dopoptoloop(startingblock) I32 startingblock; { + dTHR; I32 i; register CONTEXT *cx; for (i = startingblock; i >= 0; i--) { @@ -918,16 +994,20 @@ void dounwind(cxix) I32 cxix; { + dTHR; register CONTEXT *cx; SV **newsp; I32 optype; while (cxstack_ix > cxix) { - cx = &cxstack[cxstack_ix--]; - DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n", (long) cxstack_ix+1, - block_type[cx->cx_type])); + cx = &cxstack[cxstack_ix]; + DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n", + (long) cxstack_ix+1, block_type[cx->cx_type])); /* Note: we don't need to restore the base context info till the end. */ switch (cx->cx_type) { + case CXt_SUBST: + POPSUBST(cx); + continue; /* not break */ case CXt_SUB: POPSUB(cx); break; @@ -938,9 +1018,9 @@ I32 cxix; POPLOOP(cx); break; case CXt_NULL: - case CXt_SUBST: break; } + cxstack_ix--; } } @@ -948,6 +1028,7 @@ OP * die_where(message) char *message; { + dTHR; if (in_eval) { I32 cxix; register CONTEXT *cx; @@ -994,8 +1075,10 @@ char *message; LEAVE; - if (optype == OP_REQUIRE) - DIE("%s", SvPVx(GvSV(errgv), na)); + if (optype == OP_REQUIRE) { + char* msg = SvPVx(GvSV(errgv), na); + DIE("%s", *msg ? msg : "Compilation failed in require"); + } return pop_return(); } } @@ -1044,7 +1127,7 @@ PP(pp_entersubr) mark++; } *sp = cv; - return pp_entersub(); + return pp_entersub(ARGS); } #endif @@ -1150,6 +1233,7 @@ sortcv(a, b) const void *a; const void *b; { + dTHR; SV * const *str1 = (SV * const *)a; SV * const *str2 = (SV * const *)b; I32 oldsaveix = savestack_ix; @@ -1320,6 +1404,7 @@ PP(pp_leaveloop) mark = newsp; POPLOOP1(cx); /* Delay POPLOOP2 until stack values are safe */ + TAINT_NOT; if (gimme == G_VOID) ; /* do nothing */ else if (gimme == G_SCALAR) { @@ -1329,8 +1414,10 @@ PP(pp_leaveloop) *++newsp = &sv_undef; } else { - while (mark < SP) + while (mark < SP) { *++newsp = sv_mortalcopy(*++mark); + TAINT_NOT; /* Each item is independent */ + } } SP = newsp; PUTBACK; @@ -1357,7 +1444,7 @@ PP(pp_return) I32 optype = 0; if (curstack == sortstack) { - if (cxstack_ix == sortcxix || dopoptosub(cxstack_ix) < sortcxix) { + if (cxstack_ix == sortcxix || dopoptosub(cxstack_ix) <= sortcxix) { if (cxstack_ix > sortcxix) dounwind(sortcxix); AvARRAY(curstack)[1] = *SP; @@ -1393,6 +1480,7 @@ PP(pp_return) DIE("panic: return"); } + TAINT_NOT; if (gimme == G_SCALAR) { if (MARK < SP) *++newsp = (popsub2 && SvTEMP(*SP)) @@ -1401,9 +1489,11 @@ PP(pp_return) *++newsp = &sv_undef; } else if (gimme == G_ARRAY) { - while (++MARK <= SP) + while (++MARK <= SP) { *++newsp = (popsub2 && SvTEMP(*MARK)) ? *MARK : sv_mortalcopy(*MARK); + TAINT_NOT; /* Each item is independent */ + } } stack_sp = newsp; @@ -1465,6 +1555,7 @@ PP(pp_last) DIE("panic: last"); } + TAINT_NOT; if (gimme == G_SCALAR) { if (MARK < SP) *++newsp = ((pop2 == CXt_SUB) && SvTEMP(*SP)) @@ -1473,9 +1564,11 @@ PP(pp_last) *++newsp = &sv_undef; } else if (gimme == G_ARRAY) { - while (++MARK <= SP) + while (++MARK <= SP) { *++newsp = ((pop2 == CXt_SUB) && SvTEMP(*MARK)) ? *MARK : sv_mortalcopy(*MARK); + TAINT_NOT; /* Each item is independent */ + } } SP = newsp; PUTBACK; @@ -1549,40 +1642,45 @@ PP(pp_redo) static OP* lastgotoprobe; static OP * -dofindlabel(op,label,opstack) -OP *op; +dofindlabel(o,label,opstack,oplimit) +OP *o; char *label; OP **opstack; +OP **oplimit; { OP *kid; OP **ops = opstack; - - if (op->op_type == OP_LEAVE || - op->op_type == OP_SCOPE || - op->op_type == OP_LEAVELOOP || - op->op_type == OP_LEAVETRY) - *ops++ = cUNOP->op_first; + static char too_deep[] = "Target of goto is too deeply nested"; + + if (ops >= oplimit) + croak(too_deep); + if (o->op_type == OP_LEAVE || + o->op_type == OP_SCOPE || + o->op_type == OP_LEAVELOOP || + o->op_type == OP_LEAVETRY) + { + *ops++ = cUNOPo->op_first; + if (ops >= oplimit) + croak(too_deep); + } *ops = 0; - if (op->op_flags & OPf_KIDS) { + if (o->op_flags & OPf_KIDS) { /* First try all the kids at this level, since that's likeliest. */ - for (kid = cUNOP->op_first; kid; kid = kid->op_sibling) { + for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { if ((kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) && kCOP->cop_label && strEQ(kCOP->cop_label, label)) return kid; } - for (kid = cUNOP->op_first; kid; kid = kid->op_sibling) { + for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { if (kid == lastgotoprobe) continue; - if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) { - if (ops > opstack && - (ops[-1]->op_type == OP_NEXTSTATE || - ops[-1]->op_type == OP_DBSTATE)) - *ops = kid; - else - *ops++ = kid; - } - if (op = dofindlabel(kid,label,ops)) - return op; + if ((kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) && + (ops == opstack || + (ops[-1]->op_type != OP_NEXTSTATE && + ops[-1]->op_type != OP_DBSTATE))) + *ops++ = kid; + if (o = dofindlabel(kid, label, ops, oplimit)) + return o; } } *ops = 0; @@ -1601,7 +1699,8 @@ PP(pp_goto) OP *retop = 0; I32 ix; register CONTEXT *cx; - OP *enterops[64]; +#define GOTO_DEPTH 64 + OP *enterops[GOTO_DEPTH]; char *label; int do_dump = (op->op_type == OP_DUMP); @@ -1643,8 +1742,10 @@ PP(pp_goto) EXTEND(stack_sp, items); /* @_ could have been extended. */ Copy(AvARRAY(av), stack_sp, items, SV*); stack_sp += items; +#ifndef USE_THREADS SvREFCNT_dec(GvAV(defgv)); GvAV(defgv) = cx->blk_sub.savearray; +#endif /* USE_THREADS */ AvREAL_off(av); av_clear(av); } @@ -1727,15 +1828,34 @@ PP(pp_goto) svp = AvARRAY(padlist); } } +#ifdef USE_THREADS + if (!cx->blk_sub.hasargs) { + AV* av = (AV*)curpad[0]; + + items = AvFILL(av) + 1; + if (items) { + /* Mark is at the end of the stack. */ + EXTEND(sp, items); + Copy(AvARRAY(av), sp + 1, items, SV*); + sp += items; + PUTBACK ; + } + } +#endif /* USE_THREADS */ SAVESPTR(curpad); curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]); - if (cx->blk_sub.hasargs) { +#ifndef USE_THREADS + if (cx->blk_sub.hasargs) +#endif /* USE_THREADS */ + { AV* av = (AV*)curpad[0]; SV** ary; +#ifndef USE_THREADS cx->blk_sub.savearray = GvAV(defgv); - cx->blk_sub.argarray = av; GvAV(defgv) = (AV*)SvREFCNT_inc(av); +#endif /* USE_THREADS */ + cx->blk_sub.argarray = av; ++mark; if (items >= AvMAX(av) + 1) { @@ -1792,9 +1912,6 @@ PP(pp_goto) for (ix = cxstack_ix; ix >= 0; ix--) { cx = &cxstack[ix]; switch (cx->cx_type) { - case CXt_SUB: - gotoprobe = CvROOT(cx->blk_sub.cv); - break; case CXt_EVAL: gotoprobe = eval_root; /* XXX not good for nested eval */ break; @@ -1809,6 +1926,12 @@ PP(pp_goto) else gotoprobe = main_root; break; + case CXt_SUB: + if (CvDEPTH(cx->blk_sub.cv)) { + gotoprobe = CvROOT(cx->blk_sub.cv); + break; + } + /* FALL THROUGH */ case CXt_NULL: DIE("Can't \"goto\" outside a block"); default: @@ -1817,7 +1940,8 @@ PP(pp_goto) gotoprobe = main_root; break; } - retop = dofindlabel(gotoprobe, label, enterops); + retop = dofindlabel(gotoprobe, label, + enterops, enterops + GOTO_DEPTH); if (retop) break; lastgotoprobe = gotoprobe; @@ -1844,7 +1968,7 @@ PP(pp_goto) OP *oldop = op; for (ix = 1; enterops[ix]; ix++) { op = enterops[ix]; - (*op->op_ppaddr)(); + (*op->op_ppaddr)(ARGS); } op = oldop; } @@ -1962,15 +2086,16 @@ static OP * docatch(o) OP *o; { + dTHR; int ret; - int oldrunlevel = runlevel; + I32 oldrunlevel = runlevel; OP *oldop = op; dJMPENV; op = o; #ifdef DEBUGGING assert(CATCH_GET == TRUE); - DEBUG_l(deb("(Setting up local jumplevel, runlevel = %d)\n", runlevel+1)); + DEBUG_l(deb("(Setting up local jumplevel, runlevel = %ld)\n", (long)runlevel+1)); #endif JMPENV_PUSH(ret); switch (ret) { @@ -1998,10 +2123,12 @@ OP *o; return Nullop; } +/* With USE_THREADS, eval_owner must be held on entry to doeval */ static OP * doeval(gimme) int gimme; { + dTHR; dSP; OP *saveop = op; HV *newstash; @@ -2027,14 +2154,24 @@ int gimme; compcv = (CV*)NEWSV(1104,0); sv_upgrade((SV *)compcv, SVt_PVCV); CvUNIQUE_on(compcv); +#ifdef USE_THREADS + CvOWNER(compcv) = 0; + New(666, CvMUTEXP(compcv), 1, perl_mutex); + MUTEX_INIT(CvMUTEXP(compcv)); +#endif /* USE_THREADS */ comppad = newAV(); + av_push(comppad, Nullsv); + curpad = AvARRAY(comppad); comppad_name = newAV(); comppad_name_fill = 0; min_intro_pending = 0; - av_push(comppad, Nullsv); - curpad = AvARRAY(comppad); padix = 0; +#ifdef USE_THREADS + av_store(comppad_name, 0, newSVpv("@_", 2)); + curpad[0] = (SV*)newAV(); + SvPADMY_on(curpad[0]); /* XXX Needed? */ +#endif /* USE_THREADS */ comppadlist = newAV(); AvREAL_off(comppadlist); @@ -2087,10 +2224,18 @@ int gimme; pop_return(); lex_end(); LEAVE; - if (optype == OP_REQUIRE) - DIE("%s", SvPVx(GvSV(errgv), na)); + if (optype == OP_REQUIRE) { + char* msg = SvPVx(GvSV(errgv), na); + DIE("%s", *msg ? msg : "Compilation failed in require"); + } SvREFCNT_dec(rs); rs = SvREFCNT_inc(nrs); +#ifdef USE_THREADS + MUTEX_LOCK(&eval_mutex); + eval_owner = 0; + COND_SIGNAL(&eval_cond); + MUTEX_UNLOCK(&eval_mutex); +#endif /* USE_THREADS */ RETPUSHUNDEF; } SvREFCNT_dec(rs); @@ -2121,8 +2266,14 @@ int gimme; /* compiled okay, so do it */ CvDEPTH(compcv) = 1; - SP = stack_base + POPMARK; /* pop original mark */ +#ifdef USE_THREADS + MUTEX_LOCK(&eval_mutex); + eval_owner = 0; + COND_SIGNAL(&eval_cond); + MUTEX_UNLOCK(&eval_mutex); +#endif /* USE_THREADS */ + RETURNOP(eval_start); } @@ -2132,7 +2283,8 @@ PP(pp_require) register CONTEXT *cx; SV *sv; char *name; - char *tmpname; + char *tryname; + SV *namesv = Nullsv; SV** svp; I32 gimme = G_SCALAR; PerlIO *tryrsfp = 0; @@ -2156,61 +2308,63 @@ PP(pp_require) /* prepare to compile file */ - tmpname = savepv(name); - if (*tmpname == '/' || - (*tmpname == '.' && - (tmpname[1] == '/' || - (tmpname[1] == '.' && tmpname[2] == '/'))) + if (*name == '/' || + (*name == '.' && + (name[1] == '/' || + (name[1] == '.' && name[2] == '/'))) #ifdef DOSISH - || (tmpname[0] && tmpname[1] == ':') + || (name[0] && name[1] == ':') #endif #ifdef VMS - || (strchr(tmpname,':') || ((*tmpname == '[' || *tmpname == '<') && - (isALNUM(tmpname[1]) || strchr("$-_]>",tmpname[1])))) + || (strchr(name,':') || ((*name == '[' || *name == '<') && + (isALNUM(name[1]) || strchr("$-_]>",name[1])))) #endif ) { - tryrsfp = PerlIO_open(tmpname,"r"); + tryname = name; + tryrsfp = PerlIO_open(name,"r"); } else { AV *ar = GvAVn(incgv); I32 i; #ifdef VMS - char unixified[256]; - if (tounixspec_ts(tmpname,unixified) != NULL) - for (i = 0; i <= AvFILL(ar); i++) { - if (tounixpath_ts(SvPVx(*av_fetch(ar, i, TRUE), na),buf) == NULL) - continue; - strcat(buf,unixified); + char *unixname; + if ((unixname = tounixspec(name, Nullch)) != Nullch) +#endif + { + namesv = NEWSV(806, 0); + for (i = 0; i <= AvFILL(ar); i++) { + char *dir = SvPVx(*av_fetch(ar, i, TRUE), na); +#ifdef VMS + char *unixdir; + if ((unixdir = tounixpath(dir, Nullch)) == Nullch) + continue; + sv_setpv(namesv, unixdir); + sv_catpv(namesv, unixname); #else - for (i = 0; i <= AvFILL(ar); i++) { - (void)sprintf(buf, "%s/%s", - SvPVx(*av_fetch(ar, i, TRUE), na), name); + sv_setpvf(namesv, "%s/%s", dir, name); #endif - tryrsfp = PerlIO_open(buf, "r"); - if (tryrsfp) { - char *s = buf; - - if (*s == '.' && s[1] == '/') - s += 2; - Safefree(tmpname); - tmpname = savepv(s); - break; + tryname = SvPVX(namesv); + tryrsfp = PerlIO_open(tryname, "r"); + if (tryrsfp) { + if (tryname[0] == '.' && tryname[1] == '/') + tryname += 2; + break; + } } } } SAVESPTR(compiling.cop_filegv); - compiling.cop_filegv = gv_fetchfile(tmpname); - Safefree(tmpname); - tmpname = Nullch; + compiling.cop_filegv = gv_fetchfile(tryrsfp ? tryname : name); + SvREFCNT_dec(namesv); if (!tryrsfp) { if (op->op_type == OP_REQUIRE) { - sprintf(tokenbuf,"Can't locate %s in @INC", name); - if (instr(tokenbuf,".h ")) - strcat(tokenbuf," (change .h to .ph maybe?)"); - if (instr(tokenbuf,".ph ")) - strcat(tokenbuf," (did you run h2ph?)"); - DIE("%s",tokenbuf); + SV *msg = sv_2mortal(newSVpvf("Can't locate %s in @INC", name)); + 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?)"); + DIE("%_", msg); } RETPUSHUNDEF; @@ -2243,6 +2397,14 @@ PP(pp_require) compiling.cop_line = 0; PUTBACK; +#ifdef USE_THREADS + MUTEX_LOCK(&eval_mutex); + if (eval_owner && eval_owner != thr) + while (eval_owner) + COND_WAIT(&eval_cond, &eval_mutex); + eval_owner = thr; + MUTEX_UNLOCK(&eval_mutex); +#endif /* USE_THREADS */ return DOCATCH(doeval(G_SCALAR)); } @@ -2257,7 +2419,8 @@ PP(pp_entereval) register CONTEXT *cx; dPOPss; I32 gimme = GIMME_V, was = sub_generation; - char tmpbuf[32], *safestr; + char tmpbuf[TYPE_DIGITS(long) + 12]; + char *safestr; STRLEN len; OP *ret; @@ -2294,6 +2457,14 @@ PP(pp_entereval) if (perldb && curstash != debstash) save_lines(GvAV(compiling.cop_filegv), linestr); PUTBACK; +#ifdef USE_THREADS + MUTEX_LOCK(&eval_mutex); + if (eval_owner && eval_owner != thr) + while (eval_owner) + COND_WAIT(&eval_cond, &eval_mutex); + eval_owner = thr; + MUTEX_UNLOCK(&eval_mutex); +#endif /* USE_THREADS */ ret = doeval(gimme); if (perldb && was != sub_generation) { /* Some subs defined here. */ strcpy(safestr, "_<(eval )"); /* Anything fake and short. */ @@ -2317,6 +2488,7 @@ PP(pp_leaveeval) POPEVAL(cx); retop = pop_return(); + TAINT_NOT; if (gimme == G_VOID) MARK = newsp; else if (gimme == G_SCALAR) { @@ -2333,10 +2505,13 @@ PP(pp_leaveeval) } } else { - for (mark = newsp + 1; mark <= SP; mark++) - if (!(SvFLAGS(*mark) & SVs_TEMP)) + /* in case LEAVE wipes old return values */ + for (mark = newsp + 1; mark <= SP; mark++) { + if (!(SvFLAGS(*mark) & SVs_TEMP)) { *mark = sv_mortalcopy(*mark); - /* in case LEAVE wipes old return values */ + TAINT_NOT; /* Each item is independent */ + } + } } curpm = newpm; /* Don't pop $1 et al till now */ @@ -2397,6 +2572,7 @@ PP(pp_leavetry) POPEVAL(cx); pop_return(); + TAINT_NOT; if (gimme == G_VOID) SP = newsp; else if (gimme == G_SCALAR) { @@ -2414,10 +2590,13 @@ PP(pp_leavetry) SP = MARK; } else { - for (mark = newsp + 1; mark <= SP; mark++) - if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) + /* in case LEAVE wipes old return values */ + for (mark = newsp + 1; mark <= SP; mark++) { + if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) { *mark = sv_mortalcopy(*mark); - /* in case LEAVE wipes old return values */ + TAINT_NOT; /* Each item is independent */ + } + } } curpm = newpm; /* Don't pop $1 et al till now */