X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_hot.c;h=bf33ab872a68bbf78b4bcb79a23e9331a462a298;hb=95146c060d4701c16367f59345531d4eb7a2d283;hp=31983f18ea0318b9572e4787c1c18367fbf28f81;hpb=4aa0a1f7324b8447469670a1b2427c3ac2428bae;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_hot.c b/pp_hot.c index 31983f1..bf33ab8 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -76,6 +76,64 @@ PP(pp_gv) RETURN; } +PP(pp_gelem) +{ + GV *gv; + SV *sv; + SV *ref; + char *elem; + dSP; + + sv = POPs; + elem = SvPV(sv, na); + gv = (GV*)POPs; + ref = Nullsv; + sv = Nullsv; + switch (elem ? *elem : '\0') + { + case 'A': + if (strEQ(elem, "ARRAY")) + ref = (SV*)GvAV(gv); + break; + case 'C': + if (strEQ(elem, "CODE")) + ref = (SV*)GvCV(gv); + break; + case 'F': + if (strEQ(elem, "FILEHANDLE")) + ref = (SV*)GvIOp(gv); + break; + case 'G': + if (strEQ(elem, "GLOB")) + ref = (SV*)gv; + break; + case 'H': + if (strEQ(elem, "HASH")) + ref = (SV*)GvHV(gv); + break; + case 'N': + if (strEQ(elem, "NAME")) + sv = newSVpv(GvNAME(gv), GvNAMELEN(gv)); + break; + case 'P': + if (strEQ(elem, "PACKAGE")) + sv = newSVpv(HvNAME(GvSTASH(gv)), 0); + break; + case 'S': + if (strEQ(elem, "SCALAR")) + ref = GvSV(gv); + break; + } + if (ref) + sv = newRV(ref); + if (sv) + sv_2mortal(sv); + else + sv = &sv_undef; + XPUSHs(sv); + RETURN; +} + PP(pp_and) { dSP; @@ -148,8 +206,12 @@ PP(pp_concat) s = SvPV(left,len); sv_setpvn(TARG,s,len); } - else if (!SvOK(TARG)) + else if (SvGMAGICAL(TARG)) + mg_get(TARG); + else if (!SvOK(TARG)) { + s = SvPV_force(TARG, len); sv_setpv(TARG, ""); /* Suppress warning. */ + } s = SvPV(right,len); sv_catpvn(TARG,s,len); SETTARG; @@ -161,8 +223,12 @@ PP(pp_padsv) { dSP; dTARGET; XPUSHs(TARG); - if (op->op_private & OPpLVAL_INTRO) - SAVECLEARSV(curpad[op->op_targ]); + if (op->op_flags & OPf_MOD) { + if (op->op_private & OPpLVAL_INTRO) + SAVECLEARSV(curpad[op->op_targ]); + else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) + provide_ref(op, curpad[op->op_targ]); + } RETURN; } @@ -186,8 +252,13 @@ PP(pp_preinc) { dSP; if (SvIOK(TOPs)) { - ++SvIVX(TOPs); - SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK); + if (SvIVX(TOPs) == IV_MAX) { + sv_setnv(TOPs, (double)(SvIVX(TOPs)) + 1.0 ); + } + else { + ++SvIVX(TOPs); + SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK); + } } else sv_inc(TOPs); @@ -249,16 +320,31 @@ PP(pp_print) dSP; dMARK; dORIGMARK; GV *gv; IO *io; - register FILE *fp; + register PerlIO *fp; + MAGIC *mg; if (op->op_flags & OPf_STACKED) gv = (GV*)*++MARK; else gv = defoutgv; + if (SvMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) { + SV *sv; + + PUSHMARK(MARK-1); + *MARK = mg->mg_obj; + ENTER; + perl_call_method("PRINT", G_SCALAR); + LEAVE; + SPAGAIN; + sv = POPs; + SP = ORIGMARK; + PUSHs(sv); + RETURN; + } if (!(io = GvIO(gv))) { if (dowarn) { SV* sv = sv_newmortal(); - gv_fullname(sv,gv); + gv_fullname(sv, gv, Nullch); warn("Filehandle %s never opened", SvPV(sv,na)); } @@ -268,7 +354,7 @@ PP(pp_print) else if (!(fp = IoOFP(io))) { if (dowarn) { SV* sv = sv_newmortal(); - gv_fullname(sv,gv); + gv_fullname(sv, gv, Nullch); if (IoIFP(io)) warn("Filehandle %s opened only for input", SvPV(sv,na)); else @@ -285,7 +371,7 @@ PP(pp_print) break; MARK++; if (MARK <= SP) { - if (fwrite1(ofs, 1, ofslen, fp) == 0 || ferror(fp)) { + if (PerlIO_write(fp, ofs, ofslen) == 0 || PerlIO_error(fp)) { MARK--; break; } @@ -303,11 +389,11 @@ PP(pp_print) goto just_say_no; else { if (orslen) - if (fwrite1(ors, 1, orslen, fp) == 0 || ferror(fp)) + if (PerlIO_write(fp, ors, orslen) == 0 || PerlIO_error(fp)) goto just_say_no; if (IoFLAGS(io) & IOf_FLUSH) - if (fflush(fp) == EOF) + if (PerlIO_flush(fp) == EOF) goto just_say_no; } } @@ -348,6 +434,8 @@ PP(pp_rv2av) } } else { + GV *gv; + if (SvTYPE(sv) != SVt_PVGV) { char *sym; @@ -360,16 +448,20 @@ PP(pp_rv2av) if (op->op_flags & OPf_REF || op->op_private & HINT_STRICT_REFS) DIE(no_usym, "an ARRAY"); + if (GIMME == G_ARRAY) + RETURN; RETPUSHUNDEF; } sym = SvPV(sv,na); if (op->op_private & HINT_STRICT_REFS) DIE(no_symref, sym, "an ARRAY"); - sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVAV); + gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVAV); + } else { + gv = (GV*)sv; } - av = GvAVn(sv); + av = GvAVn(gv); if (op->op_private & OPpLVAL_INTRO) - av = save_ary(sv); + av = save_ary(gv); if (op->op_flags & OPf_REF) { PUSHs((SV*)av); RETURN; @@ -419,6 +511,8 @@ PP(pp_rv2hv) } } else { + GV *gv; + if (SvTYPE(sv) != SVt_PVGV) { char *sym; @@ -431,16 +525,22 @@ PP(pp_rv2hv) if (op->op_flags & OPf_REF || op->op_private & HINT_STRICT_REFS) DIE(no_usym, "a HASH"); + if (GIMME == G_ARRAY) { + SP--; + RETURN; + } RETSETUNDEF; } sym = SvPV(sv,na); if (op->op_private & HINT_STRICT_REFS) DIE(no_symref, sym, "a HASH"); - sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVHV); + gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVHV); + } else { + gv = (GV*)sv; } - hv = GvHVn(sv); + hv = GvHVn(gv); if (op->op_private & OPpLVAL_INTRO) - hv = save_hash(sv); + hv = save_hash(gv); if (op->op_flags & OPf_REF) { SETs((SV*)hv); RETURN; @@ -502,6 +602,7 @@ PP(pp_aassign) ary = Null(AV*); hash = Null(HV*); while (lelem <= lastlelem) { + tainted = 0; /* Each item stands on its own, taintwise. */ sv = *lelem++; switch (SvTYPE(sv)) { case SVt_PVAV: @@ -518,10 +619,10 @@ PP(pp_aassign) (void)av_store(ary,i++,sv); if (magic) mg_set(sv); + tainted = 0; } break; case SVt_PVHV: { - char *tmps; SV *tmpstr; hash = (HV*)sv; @@ -534,15 +635,17 @@ PP(pp_aassign) sv = *(relem++); else sv = &sv_no, relem++; - tmps = SvPV(sv, len); tmpstr = NEWSV(29,0); if (*relem) sv_setsv(tmpstr,*relem); /* value */ *(relem++) = tmpstr; - (void)hv_store(hash,tmps,len,tmpstr,0); + (void)hv_store_ent(hash,sv,tmpstr,0); if (magic) mg_set(tmpstr); + tainted = 0; } + if (relem == lastrelem) + warn("Odd number of elements in hash list"); } break; default: @@ -626,7 +729,7 @@ PP(pp_aassign) gid = (int)getgid(); egid = (int)getegid(); } - tainting |= (euid != uid || egid != gid); + tainting |= (uid && (euid != uid || egid != gid)); } delaymagic = 0; if (GIMME == G_ARRAY) { @@ -637,16 +740,11 @@ PP(pp_aassign) RETURN; } else { + dTARGET; SP = firstrelem; - for (relem = firstrelem; relem <= lastrelem; ++relem) { - if (SvOK(*relem)) { - dTARGET; - SETi(lastrelem - firstrelem + 1); - RETURN; - } - } - RETSETUNDEF; + SETi(lastrelem - firstrelem + 1); + RETURN; } } @@ -664,6 +762,7 @@ PP(pp_match) I32 gimme = GIMME; STRLEN len; I32 minmatch = 0; + I32 oldsave = savestack_ix; if (op->op_flags & OPf_STACKED) TARG = POPs; @@ -738,7 +837,7 @@ play_it_again: } else if (!multiline) { if (*SvPVX(pm->op_pmshort) != *s || - bcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) { + memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) { if (pm->op_pmflags & PMf_FOLD) { if (ibcmp((U8*)SvPVX(pm->op_pmshort), (U8*)s, pm->op_pmslen) ) goto nope; @@ -752,7 +851,7 @@ play_it_again: pm->op_pmshort = Nullsv; /* opt is being useless */ } } - if (regexec(rx, s, strend, truebase, minmatch, + if (pregexec(rx, s, strend, truebase, minmatch, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { curpm = pm; @@ -788,6 +887,7 @@ play_it_again: ++rx->endp[0]; goto play_it_again; } + LEAVE_SCOPE(oldsave); RETURN; } else { @@ -809,6 +909,7 @@ play_it_again: else mg->mg_len = -1; } + LEAVE_SCOPE(oldsave); RETPUSHYES; } @@ -835,6 +936,7 @@ yup: tmps = rx->startp[0] = tmps + (s - t); rx->endp[0] = tmps + SvCUR(pm->op_pmshort); } + LEAVE_SCOPE(oldsave); RETPUSHYES; nope: @@ -849,6 +951,7 @@ ret_no: mg->mg_len = -1; } } + LEAVE_SCOPE(oldsave); if (gimme == G_ARRAY) RETURN; RETPUSHNO; @@ -861,10 +964,22 @@ do_readline() register SV *sv; STRLEN tmplen = 0; STRLEN offset; - FILE *fp; + PerlIO *fp; register IO *io = GvIO(last_in_gv); register I32 type = op->op_type; + MAGIC *mg; + if (SvMAGICAL(last_in_gv) && (mg = mg_find((SV*)last_in_gv, 'q'))) { + PUSHMARK(SP); + XPUSHs(mg->mg_obj); + PUTBACK; + ENTER; + perl_call_method("READLINE", GIMME); + LEAVE; + SPAGAIN; + if (GIMME == G_SCALAR) sv_setsv(TARG, TOPs); + RETURN; + } fp = Nullfp; if (io) { fp = IoIFP(io); @@ -901,7 +1016,7 @@ do_readline() char *rstr = rslt + sizeof(unsigned short int), *begin, *end, *cp; char tmpfnam[L_tmpnam] = "SYS$SCRATCH:"; $DESCRIPTOR(dfltdsc,"SYS$DISK:[]*.*;"); - FILE *tmpfp; + PerlIO *tmpfp; STRLEN i; struct dsc$descriptor_s wilddsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; @@ -931,7 +1046,7 @@ do_readline() break; } } - if ((tmpfp = fopen(tmpfnam,"w+","fop=dlt")) != NULL) { + if ((tmpfp = PerlIO_open(tmpfnam,"w+","fop=dlt")) != NULL) { ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL); if (ok) wilddsc.dsc$w_length = (unsigned short int) strlen(wilddsc.dsc$a_pointer); while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt, @@ -941,7 +1056,7 @@ do_readline() *(end++) = '\n'; *end = '\0'; for (cp = rstr; *cp; cp++) *cp = _tolower(*cp); if (hasdir) { - if (isunix) trim_unixpath(SvPVX(tmpglob),rstr); + if (isunix) trim_unixpath(rstr,SvPVX(tmpglob)); begin = rstr; } else { @@ -949,16 +1064,20 @@ do_readline() while (*(--begin) != ']' && *begin != '>') ; ++begin; } - ok = (fputs(begin,tmpfp) != EOF); + ok = (PerlIO_puts(tmpfp,begin) != EOF); } if (cxt) (void)lib$find_file_end(&cxt); if (ok && sts != RMS$_NMF && sts != RMS$_DNF && sts != RMS$_FNF) ok = 0; if (!ok) { + if (!(sts & 1)) { + SETERRNO((sts == RMS$_SYN ? EINVAL : EVMSERR),sts); + } + PerlIO_close(tmpfp); fp = NULL; } else { - rewind(tmpfp); + PerlIO_rewind(tmpfp); IoTYPE(io) = '<'; IoIFP(io) = fp = tmpfp; } @@ -966,11 +1085,17 @@ do_readline() } #else /* !VMS */ #ifdef DOSISH +#ifdef OS2 + sv_setpv(tmpcmd, "for a in "); + sv_catsv(tmpcmd, tmpglob); + sv_catpv(tmpcmd, "; do echo \"$a\\0\\c\"; done |"); +#else sv_setpv(tmpcmd, "perlglob "); sv_catsv(tmpcmd, tmpglob); sv_catpv(tmpcmd, " |"); -#else -#ifdef CSH +#endif /* !OS2 */ +#else /* !DOSISH */ +#if defined(CSH) sv_setpvn(tmpcmd, cshname, cshlen); sv_catpv(tmpcmd, " -cf 'set nonomatch; glob "); sv_catsv(tmpcmd, tmpglob); @@ -984,8 +1109,9 @@ do_readline() sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\n\\n\\n\\n'|"); #endif #endif /* !CSH */ -#endif /* !MSDOS */ - (void)do_open(last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),Nullfp); +#endif /* !DOSISH */ + (void)do_open(last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd), + FALSE, 0, 0, Nullfp); fp = IoIFP(io); #endif /* !VMS */ LEAVE; @@ -995,7 +1121,7 @@ do_readline() SP--; } if (!fp) { - if (dowarn && !(IoFLAGS(io) & IOf_START)) + if (dowarn && io && !(IoFLAGS(io) & IOf_START)) warn("Read on closed filehandle <%s>", GvENAME(last_in_gv)); if (GIMME == G_SCALAR) { (void)SvOK_off(TARG); @@ -1020,7 +1146,7 @@ do_readline() } for (;;) { if (!sv_gets(sv, fp, offset)) { - clearerr(fp); + PerlIO_clearerr(fp); if (IoFLAGS(io) & IOf_ARGV) { fp = nextargv(last_in_gv); if (fp) @@ -1046,12 +1172,13 @@ do_readline() if (type == OP_GLOB) { char *tmps; - if (SvCUR(sv) > 0) - SvCUR(sv)--; - if (*SvEND(sv) == rschar) - *SvEND(sv) = '\0'; - else - SvCUR(sv)++; + if (SvCUR(sv) > 0 && SvCUR(rs) > 0) { + tmps = SvEND(sv) - 1; + if (*tmps == *SvPVX(rs)) { + *tmps = '\0'; + SvCUR(sv)--; + } + } for (tmps = SvPVX(sv); *tmps; tmps++) if (!isALPHA(*tmps) && !isDIGIT(*tmps) && strchr("$&*(){}[]'\";\\|?<>~`", *tmps)) @@ -1110,35 +1237,23 @@ PP(pp_enter) PP(pp_helem) { dSP; - SV** svp; + HE* he; SV *keysv = POPs; - STRLEN keylen; - char *key = SvPV(keysv, keylen); HV *hv = (HV*)POPs; I32 lval = op->op_flags & OPf_MOD; if (SvTYPE(hv) != SVt_PVHV) RETPUSHUNDEF; - svp = hv_fetch(hv, key, keylen, lval); + he = hv_fetch_ent(hv, keysv, lval, 0); if (lval) { - if (!svp || *svp == &sv_undef) - DIE(no_helem, key); + if (!he || HeVAL(he) == &sv_undef) + DIE(no_helem, SvPV(keysv, na)); if (op->op_private & OPpLVAL_INTRO) - save_svref(svp); - else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) { - SV* sv = *svp; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (!SvOK(sv)) { - (void)SvUPGRADE(sv, SVt_RV); - SvRV(sv) = (op->op_private & OPpDEREF_HV ? - (SV*)newHV() : (SV*)newAV()); - SvROK_on(sv); - SvSETMAGIC(sv); - } - } + save_svref(&HeVAL(he)); + else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) + provide_ref(op, HeVAL(he)); } - PUSHs(svp ? *svp : &sv_undef); + PUSHs(he ? HeVAL(he) : &sv_undef); RETURN; } @@ -1200,16 +1315,20 @@ PP(pp_iter) dSP; register CONTEXT *cx; SV *sv; + AV* av; EXTEND(sp, 1); cx = &cxstack[cxstack_ix]; if (cx->cx_type != CXt_LOOP) DIE("panic: pp_iter"); + av = cx->blk_loop.iterary; + if (av == curstack && cx->blk_loop.iterix >= cx->blk_oldsp) + RETPUSHNO; - if (cx->blk_loop.iterix >= cx->blk_oldsp) + if (cx->blk_loop.iterix >= AvFILL(av)) RETPUSHNO; - if (sv = AvARRAY(cx->blk_loop.iterary)[++cx->blk_loop.iterix]) { + if (sv = AvARRAY(av)[++cx->blk_loop.iterix]) { SvTEMP_off(sv); *cx->blk_loop.itervar = sv; } @@ -1240,6 +1359,7 @@ PP(pp_subst) register REGEXP *rx = pm->op_pmregexp; STRLEN len; int force_on_match = 0; + I32 oldsave = savestack_ix; if (pm->op_pmflags & PMf_CONST) /* known replacement string? */ dstr = POPs; @@ -1250,7 +1370,7 @@ PP(pp_subst) EXTEND(SP,1); } s = SvPV(TARG, len); - if (!SvPOKp(TARG) || SvREADONLY(TARG)) + if (!SvPOKp(TARG) || SvREADONLY(TARG) || (SvTYPE(TARG) == SVt_PVGV)) force_on_match = 1; force_it: @@ -1292,7 +1412,7 @@ PP(pp_subst) } else if (!multiline) { if (*SvPVX(pm->op_pmshort) != *s || - bcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) { + memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) { if (pm->op_pmflags & PMf_FOLD) { if (ibcmp((U8*)SvPVX(pm->op_pmshort), (U8*)s, pm->op_pmslen) ) goto nope; @@ -1311,7 +1431,7 @@ PP(pp_subst) c = SvPV(dstr, clen); if (clen <= rx->minlen) { /* can do inplace substitution */ - if (regexec(rx, s, strend, orig, 0, + if (pregexec(rx, s, strend, orig, 0, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { if (force_on_match) { force_on_match = 0; @@ -1342,6 +1462,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } /*SUPPRESS 560*/ @@ -1357,6 +1478,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } else if (clen) { @@ -1366,6 +1488,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } else { @@ -1373,6 +1496,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } /* NOTREACHED */ @@ -1392,7 +1516,7 @@ PP(pp_subst) d += clen; } s = rx->endp[0]; - } while (regexec(rx, s, strend, orig, s == m, + } while (pregexec(rx, s, strend, orig, s == m, Nullsv, TRUE)); /* (don't match same null twice) */ if (s != d) { i = strend - s; @@ -1402,15 +1526,17 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(sv_2mortal(newSViv((I32)iters))); + LEAVE_SCOPE(oldsave); RETURN; } PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; } } else c = Nullch; - if (regexec(rx, s, strend, orig, 0, + if (pregexec(rx, s, strend, orig, 0, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { long_way: if (force_on_match) { @@ -1443,10 +1569,11 @@ PP(pp_subst) sv_catpvn(dstr, c, clen); if (once) break; - } while (regexec(rx, s, strend, orig, s == m, Nullsv, + } while (pregexec(rx, s, strend, orig, s == m, Nullsv, safebase)); sv_catpvn(dstr, s, strend - s); + (void)SvOOK_off(TARG); Safefree(SvPVX(TARG)); SvPVX(TARG) = SvPVX(dstr); SvCUR_set(TARG, SvCUR(dstr)); @@ -1457,14 +1584,17 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(sv_2mortal(newSViv((I32)iters))); + LEAVE_SCOPE(oldsave); RETURN; } PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; nope: ++BmUSEFUL(pm->op_pmshort); PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; } @@ -1561,6 +1691,7 @@ PP(pp_entersub) register CV *cv; register CONTEXT *cx; I32 gimme; + I32 hasargs = (op->op_flags & OPf_STACKED) != 0; if (!sv) DIE("Not a CODE reference"); @@ -1604,13 +1735,24 @@ PP(pp_entersub) if (!CvROOT(cv) && !CvXSUB(cv)) { if (gv = CvGV(cv)) { - SV *tmpstr = sv_newmortal(); + SV *tmpstr; GV *ngv; - gv_efullname(tmpstr, gv); + if (SvFAKE(cv) && GvCV(gv) != cv) { /* autoloaded stub? */ + cv = GvCV(gv); + if (SvTYPE(sv) == SVt_PVGV) { + SvREFCNT_dec(GvCV((GV*)sv)); + GvCV((GV*)sv) = (CV*)SvREFCNT_inc((SV*)cv); + } + goto retry; + } + tmpstr = sv_newmortal(); + gv_efullname(tmpstr, gv, Nullch); ngv = gv_fetchmethod(GvESTASH(gv), "AUTOLOAD"); if (ngv && ngv != gv && (cv = GvCV(ngv))) { /* One more chance... */ gv = ngv; sv_setsv(GvSV(CvGV(cv)), tmpstr); /* Set CV's $AUTOLOAD */ + if (tainting) + sv_unmagic(GvSV(CvGV(cv)), 't'); goto retry; } else @@ -1619,27 +1761,31 @@ PP(pp_entersub) DIE("Undefined subroutine called"); } - if ((op->op_private & OPpDEREF_DB) && !CvXSUB(cv)) { + gimme = GIMME; + if ((op->op_private & OPpENTERSUB_DB)) { sv = GvSV(DBsub); save_item(sv); - if (SvFLAGS(cv) & SVpcv_ANON) /* Is GV potentially non-unique? */ + gv = CvGV(cv); + if ( CvFLAGS(cv) & (CVf_ANON | CVf_CLONED) + || strEQ(GvNAME(gv), "END") ) { + /* GV is potentially non-unique */ sv_setsv(sv, newRV((SV*)cv)); + } else { - gv = CvGV(cv); - gv_efullname(sv,gv); + gv_efullname(sv, gv, Nullch); } cv = GvCV(DBsub); + if (CvXSUB(cv)) curcopdb = curcop; if (!cv) DIE("No DBsub routine"); } - gimme = GIMME; - if (CvXSUB(cv)) { if (CvOLDSTYLE(cv)) { I32 (*fp3)_((int,int,int)); dMARK; register I32 items = SP - MARK; + /* We dont worry to copy from @_. */ while (sp > mark) { sp[1] = sp[0]; sp--; @@ -1655,6 +1801,30 @@ PP(pp_entersub) I32 markix = TOPMARK; PUTBACK; + + if (!hasargs) { + /* Need to copy @_ to stack. Alternative may be to + * switch stack to @_, and copy return values + * back. This would allow popping @_ in XSUB, e.g.. XXXX */ + AV* av = GvAV(defgv); + I32 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 ; + } + } + if (curcopdb) { /* We assume that the first + XSUB in &DB::sub is the + called one. */ + SAVESPTR(curcop); + curcop = curcopdb; + curcopdb = NULL; + } + /* Do we need to open block here? XXXX */ (void)(*CvXSUB(cv))(cv); /* Enforce some sanity in scalar context. */ @@ -1672,7 +1842,6 @@ PP(pp_entersub) else { dMARK; register I32 items = SP - MARK; - I32 hasargs = (op->op_flags & OPf_STACKED) != 0; AV* padlist = CvPADLIST(cv); SV** svp = AvARRAY(padlist); push_return(op->op_next); @@ -1780,23 +1949,31 @@ PP(pp_aelem) DIE(no_aelem, elem); if (op->op_private & OPpLVAL_INTRO) save_svref(svp); - else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) { - SV* sv = *svp; - if (SvGMAGICAL(sv)) - mg_get(sv); - if (!SvOK(sv)) { - (void)SvUPGRADE(sv, SVt_RV); - SvRV(sv) = (op->op_private & OPpDEREF_HV ? - (SV*)newHV() : (SV*)newAV()); - SvROK_on(sv); - SvSETMAGIC(sv); - } - } + else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) + provide_ref(op, *svp); } PUSHs(svp ? *svp : &sv_undef); RETURN; } +void +provide_ref(op, sv) +OP* op; +SV* sv; +{ + if (SvGMAGICAL(sv)) + mg_get(sv); + if (!SvOK(sv)) { + if (SvREADONLY(sv)) + croak(no_modify); + (void)SvUPGRADE(sv, SVt_RV); + SvRV(sv) = (op->op_private & OPpDEREF_HV ? + (SV*)newHV() : (SV*)newAV()); + SvROK_on(sv); + SvSETMAGIC(sv); + } +} + PP(pp_method) { dSP; @@ -1816,9 +1993,10 @@ PP(pp_method) else { GV* iogv; char* packname = 0; + STRLEN packlen; if (!SvOK(sv) || - !(packname = SvPV(sv, na)) || + !(packname = SvPV(sv, packlen)) || !(iogv = gv_fetchpv(packname, FALSE, SVt_PVIO)) || !(ob=(SV*)GvIO(iogv))) { @@ -1826,9 +2004,9 @@ PP(pp_method) HV *stash; if (!packname || !isALPHA(*packname)) DIE("Can't call method \"%s\" without a package or object reference", name); - if (!(stash = gv_stashpv(packname, FALSE))) { - if (gv_stashpv("UNIVERSAL", FALSE)) - stash = gv_stashpv(packname, TRUE); + if (!(stash = gv_stashpvn(packname, packlen, FALSE))) { + if (gv_stashpvn("UNIVERSAL", 9, FALSE)) + stash = gv_stashpvn(packname, packlen, TRUE); else DIE("Can't call method \"%s\" in empty package \"%s\"", name, packname); @@ -1837,10 +2015,10 @@ DIE("Can't call method \"%s\" without a package or object reference", name); if (!gv) DIE("Can't locate object method \"%s\" via package \"%s\"", name, packname); - SETs(gv); + SETs((SV*)gv); RETURN; } - *(stack_base + TOPMARK + 1) = iogv; + *(stack_base + TOPMARK + 1) = sv_2mortal(newRV((SV*)iogv)); } if (!ob || !SvOBJECT(ob)) { @@ -1856,7 +2034,7 @@ DIE("Can't call method \"%s\" without a package or object reference", name); name, HvNAME(SvSTASH(ob))); } - SETs(gv); + SETs((SV*)gv); RETURN; }