X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=1fbafc768f3b57f03993978f6bd96e328ac927c5;hb=a14cb26abd9e94e845d7de891545ccdb8fb0fad9;hp=21dc2492431db7cd312828f1c5c229351ffd95ef;hpb=3c4f770c93854ee7c6f0c96a5913404f60061eb2;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index 21dc249..1fbafc7 100644 --- a/op.c +++ b/op.c @@ -40,6 +40,8 @@ static OP *too_many_arguments _((OP *o, char* name)); static void null _((OP* o)); static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)); +static OP *newDEFSVOP _((void)); +static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp)); static char* gv_ename(GV *gv) @@ -84,9 +86,18 @@ assertref(OP *o) int type = o->op_type; if (type != OP_AELEM && type != OP_HELEM) { yyerror(form("Can't use subscript on %s", op_desc[type])); - if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV) - warn("(Did you mean $ or @ instead of %c?)\n", - type == OP_ENTERSUB ? '&' : '%'); + if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV) { + dTHR; + SV *msg = sv_2mortal( + newSVpvf("(Did you mean $ or @ instead of %c?)\n", + type == OP_ENTERSUB ? '&' : '%')); + if (in_eval & 2) + warn("%_", msg); + else if (in_eval) + sv_catsv(GvSV(errgv), msg); + else + PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg)); + } } } @@ -107,9 +118,9 @@ pad_allocmy(char *name) } croak("Can't use global %s in \"my\"",name); } - if (dowarn && AvFILL(comppad_name) >= 0) { + if (dowarn && AvFILLp(comppad_name) >= 0) { SV **svp = AvARRAY(comppad_name); - for (off = AvFILL(comppad_name); off > comppad_name_floor; off--) { + for (off = AvFILLp(comppad_name); off > comppad_name_floor; off--) { if ((sv = svp[off]) && sv != &sv_undef && SvIVX(sv) == 999999999 /* var is in open scope */ @@ -147,16 +158,7 @@ pad_allocmy(char *name) } static PADOFFSET -#ifndef CAN_PROTOTYPE -pad_findlex(name, newoff, seq, startcv, cx_ix) -char *name; -PADOFFSET newoff; -U32 seq; -CV* startcv; -I32 cx_ix; -#else pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix) -#endif { dTHR; CV *cv; @@ -175,7 +177,7 @@ pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix) continue; curname = (AV*)*svp; svp = AvARRAY(curname); - for (off = AvFILL(curname); off > 0; off--) { + for (off = AvFILLp(curname); off > 0; off--) { if ((sv = svp[off]) && sv != &sv_undef && seq <= SvIVX(sv) && @@ -306,7 +308,7 @@ pad_findmy(char *name) #endif /* USE_THREADS */ /* The one we're looking for is probably just before comppad_name_fill. */ - for (off = AvFILL(comppad_name); off > 0; off--) { + for (off = AvFILLp(comppad_name); off > 0; off--) { if ((sv = svp[off]) && sv != &sv_undef && (!SvIVX(sv) || @@ -344,7 +346,7 @@ pad_leavemy(I32 fill) } } /* "Deintroduce" my variables that are leaving with this scope. */ - for (off = AvFILL(comppad_name); off > fill; off--) { + for (off = AvFILLp(comppad_name); off > fill; off--) { if ((sv = svp[off]) && sv != &sv_undef && SvIVX(sv) == 999999999) SvIVX(sv) = cop_seqmax; } @@ -363,13 +365,13 @@ pad_alloc(I32 optype, U32 tmptype) pad_reset(); if (tmptype & SVs_PADMY) { do { - sv = *av_fetch(comppad, AvFILL(comppad) + 1, TRUE); + sv = *av_fetch(comppad, AvFILLp(comppad) + 1, TRUE); } while (SvPADBUSY(sv)); /* need a fresh one */ - retval = AvFILL(comppad); + retval = AvFILLp(comppad); } else { SV **names = AvARRAY(comppad_name); - SSize_t names_fill = AvFILL(comppad_name); + SSize_t names_fill = AvFILLp(comppad_name); for (;;) { /* * "foreach" index vars temporarily become aliases to non-"my" @@ -392,19 +394,15 @@ pad_alloc(I32 optype, U32 tmptype) (unsigned long) thr, (unsigned long) curpad, (long) retval, op_name[optype])); #else - DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad alloc %ld for %s\n", + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx alloc %ld for %s\n", + (unsigned long) curpad, (long) retval, op_name[optype])); #endif /* USE_THREADS */ return (PADOFFSET)retval; } SV * -#ifndef CAN_PROTOTYPE -pad_sv(po) -PADOFFSET po; -#else pad_sv(PADOFFSET po) -#endif /* CAN_PROTOTYPE */ { dTHR; #ifdef USE_THREADS @@ -413,18 +411,14 @@ pad_sv(PADOFFSET po) #else if (!po) croak("panic: pad_sv po"); - DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad sv %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx sv %d\n", + (unsigned long) curpad, po)); #endif /* USE_THREADS */ return curpad[po]; /* eventually we'll turn this into a macro */ } void -#ifndef CAN_PROTOTYPE -pad_free(po) -PADOFFSET po; -#else pad_free(PADOFFSET po) -#endif /* CAN_PROTOTYPE */ { dTHR; if (!curpad) @@ -437,7 +431,8 @@ pad_free(PADOFFSET po) DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx free %d\n", (unsigned long) thr, (unsigned long) curpad, po)); #else - DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad free %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx free %d\n", + (unsigned long) curpad, po)); #endif /* USE_THREADS */ if (curpad[po] && curpad[po] != &sv_undef) SvPADTMP_off(curpad[po]); @@ -446,12 +441,7 @@ pad_free(PADOFFSET po) } void -#ifndef CAN_PROTOTYPE -pad_swipe(po) -PADOFFSET po; -#else pad_swipe(PADOFFSET po) -#endif /* CAN_PROTOTYPE */ { dTHR; if (AvARRAY(comppad) != curpad) @@ -462,7 +452,8 @@ pad_swipe(PADOFFSET po) DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx swipe %d\n", (unsigned long) thr, (unsigned long) curpad, po)); #else - DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx swipe %d\n", + (unsigned long) curpad, po)); #endif /* USE_THREADS */ SvPADTMP_off(curpad[po]); curpad[po] = NEWSV(1107,0); @@ -471,9 +462,16 @@ pad_swipe(PADOFFSET po) padix = po - 1; } +/* XXX pad_reset() is currently disabled because it results in serious bugs. + * It causes pad temp TARGs to be shared between OPs. Since TARGs are pushed + * on the stack by OPs that use them, there are several ways to get an alias + * to a shared TARG. Such an alias will change randomly and unpredictably. + * We avoid doing this until we can think of a Better Way. + * GSAR 97-10-29 */ void pad_reset(void) { +#ifdef USE_BROKEN_PAD_RESET dTHR; register I32 po; @@ -483,7 +481,8 @@ pad_reset(void) DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx reset\n", (unsigned long) thr, (unsigned long) curpad)); #else - DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad reset\n")); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx reset\n", + (unsigned long) curpad)); #endif /* USE_THREADS */ if (!tainting) { /* Can't mix tainted and non-tainted temporaries. */ for (po = AvMAX(comppad); po > padix_floor; po--) { @@ -492,40 +491,57 @@ pad_reset(void) } padix = padix_floor; } +#endif pad_reset_pending = FALSE; } #ifdef USE_THREADS -/* find_thread_magical is not reentrant */ +/* find_threadsv is not reentrant */ PADOFFSET -find_thread_magical(char *name) +find_threadsv(char *name) { dTHR; char *p; PADOFFSET key; SV **svp; - /* We currently only handle single character magicals */ - p = strchr(per_thread_magicals, *name); + /* We currently only handle names of a single character */ + p = strchr(threadsv_names, *name); if (!p) return NOT_IN_PAD; - key = p - per_thread_magicals; - svp = av_fetch(thr->magicals, key, FALSE); + key = p - threadsv_names; + svp = av_fetch(thr->threadsv, key, FALSE); if (!svp) { SV *sv = NEWSV(0, 0); - av_store(thr->magicals, key, sv); + av_store(thr->threadsv, key, sv); + thr->threadsvp = AvARRAY(thr->threadsv); /* * Some magic variables used to be automagically initialised * in gv_fetchpv. Those which are now per-thread magicals get * initialised here instead. */ switch (*name) { + case '_': + break; case ';': sv_setpv(sv, "\034"); + sv_magic(sv, 0, 0, name, 1); break; + case '&': + case '`': + case '\'': + sawampersand = TRUE; + SvREADONLY_on(sv); + /* FALL THROUGH */ + + /* XXX %! tied to Errno.pm needs to be added here. + * See gv_fetchpv(). */ + /* case '!': */ + + default: + sv_magic(sv, 0, 0, name, 1); } - sv_magic(sv, 0, 0, name, 1); DEBUG_L(PerlIO_printf(PerlIO_stderr(), - "find_thread_magical: new SV %p for $%s%c\n", + "find_threadsv: new SV %p for $%s%c\n", sv, (*name < 32) ? "^" : "", (*name < 32) ? toCTRL(*name) : *name)); } @@ -559,7 +575,7 @@ op_free(OP *o) break; #ifdef USE_THREADS case OP_THREADSV: - o->op_targ = 0; /* Was holding index into thr->magicals AV. */ + o->op_targ = 0; /* Was holding index into thr->threadsv AV. */ break; #endif /* USE_THREADS */ default: @@ -594,8 +610,7 @@ op_free(OP *o) /* FALL THROUGH */ case OP_PUSHRE: case OP_MATCH: - pregfree(cPMOPo->op_pmregexp); - SvREFCNT_dec(cPMOPo->op_pmshort); + ReREFCNT_dec(cPMOPo->op_pmregexp); break; } @@ -608,7 +623,7 @@ op_free(OP *o) static void null(OP *o) { - if (o->op_type != OP_NULL && o->op_targ > 0) + if (o->op_type != OP_NULL && o->op_type != OP_THREADSV && o->op_targ > 0) pad_free(o->op_targ); o->op_targ = o->op_type; o->op_type = OP_NULL; @@ -1035,8 +1050,6 @@ modkids(OP *o, I32 type) return o; } -static I32 modcount; - OP * mod(OP *o, I32 type) { @@ -1151,6 +1164,7 @@ mod(OP *o, I32 type) /* FALL THROUGH */ case OP_GV: case OP_AV2ARYLEN: + hints |= HINT_BLOCK_SCOPE; case OP_SASSIGN: case OP_AELEMFAST: modcount++; @@ -1230,6 +1244,7 @@ mod(OP *o, I32 type) else if (!type) { o->op_private |= OPpLVAL_INTRO; o->op_flags &= ~OPf_SPECIAL; + hints |= HINT_BLOCK_SCOPE; } else if (type != OP_GREPSTART && type != OP_ENTERSUB) o->op_flags |= OPf_REF; @@ -1389,8 +1404,9 @@ my(OP *o) if (type == OP_LIST) { for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) my(kid); - } - else if (type != OP_PADSV && + } else if (type == OP_UNDEF) { + return o; + } else if (type != OP_PADSV && type != OP_PADAV && type != OP_PADHV && type != OP_PUSHMARK) @@ -1492,7 +1508,7 @@ block_start(int full) int retval = savestack_ix; SAVEI32(comppad_name_floor); if (full) { - if ((comppad_name_fill = AvFILL(comppad_name)) > 0) + if ((comppad_name_fill = AvFILLp(comppad_name)) > 0) comppad_name_floor = comppad_name_fill; else comppad_name_floor = 0; @@ -1524,6 +1540,18 @@ block_end(I32 floor, OP *seq) return retval; } +static OP * +newDEFSVOP(void) +{ +#ifdef USE_THREADS + OP *o = newOP(OP_THREADSV, 0); + o->op_targ = find_threadsv("_"); + return o; +#else + return newSVREF(newGVOP(OP_GV, 0, defgv)); +#endif /* USE_THREADS */ +} + void newPROG(OP *o) { @@ -1549,7 +1577,7 @@ newPROG(OP *o) CV *cv = perl_get_cv("DB::postponed", FALSE); if (cv) { dSP; - PUSHMARK(sp); + PUSHMARK(SP); XPUSHs((SV*)compiling.cop_filegv); PUTBACK; perl_call_sv((SV*)cv, G_DISCARD); @@ -1564,7 +1592,6 @@ localize(OP *o, I32 lex) if (o->op_flags & OPf_PARENS) list(o); else { - scalar(o); if (dowarn && bufptr > oldbufptr && bufptr[-1] == ',') { char *s; for (s = bufptr; *s && (isALNUM(*s) || strchr("@$%, ",*s)); s++) ; @@ -1587,7 +1614,7 @@ jmaybe(OP *o) OP *o2; #ifdef USE_THREADS o2 = newOP(OP_THREADSV, 0); - o2->op_targ = find_thread_magical(";"); + o2->op_targ = find_threadsv(";"); #else o2 = newSVREF(newGVOP(OP_GV, 0, gv_fetchpv(";", TRUE, SVt_PV))), #endif /* USE_THREADS */ @@ -1621,6 +1648,12 @@ fold_constants(register OP *o) case OP_LCFIRST: case OP_UC: case OP_LC: + case OP_SLT: + case OP_SGT: + case OP_SLE: + case OP_SGE: + case OP_SCMP: + if (o->op_private & OPpLOCALE) goto nope; } @@ -1653,9 +1686,12 @@ fold_constants(register OP *o) if (type == OP_RV2GV) return newGVOP(OP_GV, 0, (GV*)sv); else { - if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK) { + /* try to smush double to int, but don't smush -2.0 to -2 */ + if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK && + type != OP_NEGATE) + { IV iv = SvIV(sv); - if ((double)iv == SvNV(sv)) { /* can we smush double to int */ + if ((double)iv == SvNV(sv)) { SvREFCNT_dec(sv); sv = newSViv(iv); } @@ -1914,7 +1950,12 @@ newUNOP(I32 type, I32 flags, OP *first) unop->op_first = first; unop->op_flags = flags | OPf_KIDS; unop->op_private = 1 | (flags >> 8); - +#if 1 + if(type == OP_STUDY && first->op_type == OP_MATCH) { + first->op_type = OP_PUSHRE; + first->op_ppaddr = ppaddr[OP_PUSHRE]; + } +#endif unop = (UNOP*) CHECKOP(type, unop); if (unop->op_next) return (OP*)unop; @@ -1966,12 +2007,13 @@ pmtrans(OP *o, OP *expr, OP *repl) register I32 j; I32 Delete; I32 complement; + I32 squash; register short *tbl; tbl = (short*)cPVOPo->op_pv; complement = o->op_private & OPpTRANS_COMPLEMENT; Delete = o->op_private & OPpTRANS_DELETE; - /* squash = o->op_private & OPpTRANS_SQUASH; */ + squash = o->op_private & OPpTRANS_SQUASH; if (complement) { Zero(tbl, 256, short); @@ -1995,6 +2037,8 @@ pmtrans(OP *o, OP *expr, OP *repl) else { if (!rlen && !Delete) { r = t; rlen = tlen; + if (!squash) + o->op_private |= OPpTRANS_COUNTONLY; } for (i = 0; i < 256; i++) tbl[i] = -1; @@ -2065,7 +2109,6 @@ pmruntime(OP *o, OP *expr, OP *repl) pm->op_pmregexp = pregcomp(p, p + plen, pm); if (strEQ("\\s+", pm->op_pmregexp->precomp)) pm->op_pmflags |= PMf_WHITE; - hoistmust(pm); op_free(expr); } else { @@ -2101,7 +2144,7 @@ pmruntime(OP *o, OP *expr, OP *repl) #ifdef USE_THREADS else if (repl->op_type == OP_THREADSV && strchr("&`'123456789+", - per_thread_magicals[repl->op_targ])) + threadsv_names[repl->op_targ])) { curop = 0; } @@ -2385,6 +2428,7 @@ newASSIGNOP(I32 flags, OP *left, I32 optype, OP *right) } if (list_assignment(left)) { + dTHR; modcount = 0; eval_start = right; /* Grandfathering $[ assignment here. Bletch.*/ left = mod(left, OP_AASSIGN); @@ -2573,9 +2617,17 @@ intro_my(void) OP * newLOGOP(I32 type, I32 flags, OP *first, OP *other) { + return new_logop(type, flags, &first, &other); +} + +static OP * +new_logop(I32 type, I32 flags, OP** firstp, OP** otherp) +{ dTHR; LOGOP *logop; OP *o; + OP *first = *firstp; + OP *other = *otherp; if (type == OP_XOR) /* Not short circuit, but here by precedence. */ return newBINOP(type, flags, scalar(first), scalar(other)); @@ -2589,7 +2641,7 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other) else type = OP_AND; o = first; - first = cUNOPo->op_first; + first = *firstp = cUNOPo->op_first; if (o->op_next) first->op_next = o->op_next; cUNOPo->op_first = Nullop; @@ -2601,10 +2653,12 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other) warn("Probable precedence problem on %s", op_desc[type]); if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) { op_free(first); + *firstp = Nullop; return other; } else { op_free(other); + *otherp = Nullop; return first; } } @@ -2623,7 +2677,7 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other) case OP_NULL: if (k2 && k2->op_type == OP_READLINE && (k2->op_flags & OPf_STACKED) - && (k1->op_type == OP_RV2SV || k1->op_type == OP_PADSV)) + && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) warnop = k2->op_type; break; @@ -2784,14 +2838,33 @@ newLOOPOP(I32 flags, I32 debuggable, OP *expr, OP *block) if (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB)) { expr = newUNOP(OP_DEFINED, 0, - newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr) ); + newASSIGNOP(0, newDEFSVOP(), 0, expr) ); + } else if (expr->op_flags & OPf_KIDS) { + OP *k1 = ((UNOP*)expr)->op_first; + OP *k2 = (k1) ? k1->op_sibling : NULL; + switch (expr->op_type) { + case OP_NULL: + if (k2 && k2->op_type == OP_READLINE + && (k2->op_flags & OPf_STACKED) + && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + + case OP_SASSIGN: + if (k1->op_type == OP_READDIR + || k1->op_type == OP_GLOB + || k1->op_type == OP_EACH) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + } } } listop = append_elem(OP_LINESEQ, block, newOP(OP_UNSTACK, 0)); - o = newLOGOP(OP_AND, 0, expr, listop); + o = new_logop(OP_AND, 0, &expr, &listop); - ((LISTOP*)listop)->op_last->op_next = LINKLIST(o); + if (listop) + ((LISTOP*)listop)->op_last->op_next = LINKLIST(o); if (once && o != listop) o->op_next = ((LOGOP*)cUNOPo->op_first)->op_other; @@ -2818,7 +2891,25 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) { expr = newUNOP(OP_DEFINED, 0, - newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr) ); + newASSIGNOP(0, newDEFSVOP(), 0, expr) ); + } else if (expr && (expr->op_flags & OPf_KIDS)) { + OP *k1 = ((UNOP*)expr)->op_first; + OP *k2 = (k1) ? k1->op_sibling : NULL; + switch (expr->op_type) { + case OP_NULL: + if (k2 && k2->op_type == OP_READLINE + && (k2->op_flags & OPf_STACKED) + && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + + case OP_SASSIGN: + if (k1->op_type == OP_READDIR + || k1->op_type == OP_GLOB + || k1->op_type == OP_EACH) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + } } if (!block) @@ -2839,14 +2930,17 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b redo = LINKLIST(listop); if (expr) { - o = newLOGOP(OP_AND, 0, expr, scalar(listop)); + copline = whileline; + scalar(listop); + o = new_logop(OP_AND, 0, &expr, &listop); if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) { op_free(expr); /* oops, it's a while (0) */ op_free((OP*)loop); - return Nullop; /* (listop already freed by newLOGOP) */ + return Nullop; /* listop already freed by new_logop */ } - ((LISTOP*)listop)->op_last->op_next = condop = - (o == listop ? redo : LINKLIST(o)); + if (listop) + ((LISTOP*)listop)->op_last->op_next = condop = + (o == listop ? redo : LINKLIST(o)); if (!next) next = condop; } @@ -2877,18 +2971,7 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b } OP * -#ifndef CAN_PROTOTYPE -newFOROP(flags,label,forline,sv,expr,block,cont) -I32 flags; -char *label; -line_t forline; -OP* sv; -OP* expr; -OP*block; -OP*cont; -#else newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont) -#endif /* CAN_PROTOTYPE */ { LOOP *loop; OP *wop; @@ -2905,11 +2988,22 @@ newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont op_free(sv); sv = Nullop; } + else if (sv->op_type == OP_THREADSV) { /* per-thread variable */ + padoff = sv->op_targ; + iterflags |= OPf_SPECIAL; + op_free(sv); + sv = Nullop; + } else croak("Can't use %s for loop variable", op_desc[sv->op_type]); } else { +#ifdef USE_THREADS + padoff = find_threadsv("_"); + iterflags |= OPf_SPECIAL; +#else sv = newGVOP(OP_GV, 0, defgv); +#endif } if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) { expr = scalar(ref(expr, OP_ITER)); @@ -2932,10 +3026,14 @@ newLOOPEX(I32 type, OP *label) dTHR; OP *o; if (type != OP_GOTO || label->op_type == OP_CONST) { - o = newPVOP(type, 0, savepv( - label->op_type == OP_CONST - ? SvPVx(((SVOP*)label)->op_sv, na) - : "" )); + /* "last()" means "last" */ + if (label->op_type == OP_STUB && (label->op_flags & OPf_PARENS)) + o = newOP(type, OPf_SPECIAL); + else { + o = newPVOP(type, 0, savepv(label->op_type == OP_CONST + ? SvPVx(((SVOP*)label)->op_sv, na) + : "")); + } op_free(label); } else { @@ -2986,7 +3084,7 @@ cv_undef(CV *cv) if (CvPADLIST(cv)) { /* may be during global destruction */ if (SvREFCNT(CvPADLIST(cv))) { - I32 i = AvFILL(CvPADLIST(cv)); + I32 i = AvFILLp(CvPADLIST(cv)); while (i >= 0) { SV** svp = av_fetch(CvPADLIST(cv), i--, FALSE); SV* sv = svp ? *svp : Nullsv; @@ -3040,7 +3138,7 @@ CV* cv; pname = AvARRAY(pad_name); ppad = AvARRAY(pad); - for (ix = 1; ix <= AvFILL(pad_name); ix++) { + for (ix = 1; ix <= AvFILLp(pad_name); ix++) { if (SvPOK(pname[ix])) PerlIO_printf(Perl_debug_log, "\t%4d. 0x%lx (%s\"%s\" %ld-%ld)\n", ix, ppad[ix], @@ -3063,8 +3161,8 @@ cv_clone2(CV *proto, CV *outside) AV* protopad = (AV*)*av_fetch(protopadlist, 1, FALSE); SV** pname = AvARRAY(protopad_name); SV** ppad = AvARRAY(protopad); - I32 fname = AvFILL(protopad_name); - I32 fpad = AvFILL(protopad); + I32 fname = AvFILLp(protopad_name); + I32 fpad = AvFILLp(protopad); AV* comppadlist; CV* cv; @@ -3109,7 +3207,7 @@ cv_clone2(CV *proto, CV *outside) av_store(comppadlist, 0, (SV*)comppad_name); av_store(comppadlist, 1, (SV*)comppad); CvPADLIST(cv) = comppadlist; - av_fill(comppad, AvFILL(protopad)); + av_fill(comppad, AvFILLp(protopad)); curpad = AvARRAY(comppad); av = newAV(); /* will be @_ */ @@ -3216,16 +3314,27 @@ cv_ckproto(CV *cv, GV *gv, char *p) SV * cv_const_sv(CV *cv) { - OP *o; - SV *sv; - if (!cv || !SvPOK(cv) || SvCUR(cv)) return Nullsv; + return op_const_sv(CvSTART(cv), cv); +} + +SV * +op_const_sv(OP *o, CV *cv) +{ + SV *sv = Nullsv; + + if(!o) + return Nullsv; + + if(o->op_type == OP_LINESEQ && cLISTOPo->op_first) + o = cLISTOPo->op_first->op_sibling; - sv = Nullsv; - for (o = CvSTART(cv); o; o = o->op_next) { + for (; o; o = o->op_next) { OPCODE type = o->op_type; - + + if(sv && o->op_next == o) + return sv; if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK) continue; if (type == OP_LEAVESUB || type == OP_RETURN) @@ -3234,7 +3343,7 @@ cv_const_sv(CV *cv) return Nullsv; if (type == OP_CONST) sv = cSVOPo->op_sv; - else if (type == OP_PADSV) { + else if (type == OP_PADSV && cv) { AV* padav = (AV*)(AvARRAY(CvPADLIST(cv))[1]); sv = padav ? AvARRAY(padav)[o->op_targ] : Nullsv; if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1)) @@ -3253,7 +3362,8 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) { dTHR; char *name = o ? SvPVx(cSVOPo->op_sv, na) : Nullch; - GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV); + GV *gv = gv_fetchpv(name ? name : "__ANON__", + GV_ADDMULTI | (block ? 0 : GV_NOINIT), SVt_PVCV); char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch; register CV *cv; I32 ix; @@ -3263,6 +3373,23 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) if (proto) SAVEFREEOP(proto); + if (SvTYPE(gv) != SVt_PVGV) { /* Prototype now, and had + maximum a prototype before. */ + if (SvTYPE(gv) > SVt_NULL) { + if (!SvPOK((SV*)gv) && !(SvIOK((SV*)gv) && SvIVX((SV*)gv) == -1)) + warn("Runaway prototype"); + cv_ckproto((CV*)gv, NULL, ps); + } + if (ps) + sv_setpv((SV*)gv, ps); + else + sv_setiv((SV*)gv, -1); + SvREFCNT_dec(compcv); + cv = compcv = NULL; + sub_generation++; + goto noblock; + } + if (!name || GvCVGEN(gv)) cv = Nullcv; else if (cv = GvCV(gv)) { @@ -3270,16 +3397,21 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) /* already defined (or promised)? */ if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) { SV* const_sv; + bool const_changed = TRUE; if (!block) { /* just a "sub foo;" when &foo is already defined */ SAVEFREESV(compcv); goto done; } /* ahem, death to those who redefine active sort subs */ - if (curstack == sortstack && sortcop == CvSTART(cv)) + if (curstackinfo->si_type == SI_SORT && sortcop == CvSTART(cv)) croak("Can't redefine active sort subroutine %s", name); - const_sv = cv_const_sv(cv); - if (const_sv || dowarn) { + if(const_sv = cv_const_sv(cv)) + const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv)); + if ((const_sv && const_changed) || dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv)) + && HvNAME(GvSTASH(CvGV(cv))) + && strEQ(HvNAME(GvSTASH(CvGV(cv))), + "autouse"))) { line_t oldline = curcop->cop_line; curcop->cop_line = copline; warn(const_sv ? "Constant subroutine %s redefined" @@ -3341,17 +3473,18 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) } } if (!block) { + noblock: copline = NOLINE; LEAVE_SCOPE(floor); return cv; } - if (AvFILL(comppad_name) < AvFILL(comppad)) - av_store(comppad_name, AvFILL(comppad), Nullsv); + if (AvFILLp(comppad_name) < AvFILLp(comppad)) + av_store(comppad_name, AvFILLp(comppad), Nullsv); if (CvCLONE(cv)) { SV **namep = AvARRAY(comppad_name); - for (ix = AvFILL(comppad); ix > 0; ix--) { + for (ix = AvFILLp(comppad); ix > 0; ix--) { SV *namesv; if (SvIMMORTAL(curpad[ix])) @@ -3377,7 +3510,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) av_store(comppad, 0, (SV*)av); AvFLAGS(av) = AVf_REIFY; - for (ix = AvFILL(comppad); ix > 0; ix--) { + for (ix = AvFILLp(comppad); ix > 0; ix--) { if (SvIMMORTAL(curpad[ix])) continue; if (!SvPADMY(curpad[ix])) @@ -3396,7 +3529,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) if (PERLDB_SUBLINE && curstash != debstash) { SV *sv = NEWSV(0,0); SV *tmpstr = sv_newmortal(); - static GV *db_postponed; + GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); CV *cv; HV *hv; @@ -3405,14 +3538,11 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) (long)subline, (long)curcop->cop_line); gv_efullname3(tmpstr, gv, Nullch); hv_store(GvHV(DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0); - if (!db_postponed) { - db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); - } hv = GvHVn(db_postponed); if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr)) && (cv = GvCV(db_postponed))) { dSP; - PUSHMARK(sp); + PUSHMARK(SP); XPUSHs(tmpstr); PUTBACK; perl_call_sv((SV*)cv, G_DISCARD); @@ -3428,7 +3558,6 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) ENTER; SAVESPTR(compiling.cop_filegv); SAVEI16(compiling.cop_line); - SAVEI32(perldb); save_svref(&rs); sv_setsv(rs, nrs); @@ -3462,6 +3591,33 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block) return cv; } +void +newCONSTSUB(HV *stash, char *name, SV *sv) +{ + dTHR; + U32 oldhints = hints; + HV *old_cop_stash = curcop->cop_stash; + HV *old_curstash = curstash; + line_t oldline = curcop->cop_line; + curcop->cop_line = copline; + + hints &= ~HINT_BLOCK_SCOPE; + if(stash) + curstash = curcop->cop_stash = stash; + + newSUB( + start_subparse(FALSE, 0), + newSVOP(OP_CONST, 0, newSVpv(name,0)), + newSVOP(OP_CONST, 0, &sv_no), /* SvPV(&sv_no) == "" -- GMB */ + newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) + ); + + hints = oldhints; + curcop->cop_stash = old_cop_stash; + curstash = old_curstash; + curcop->cop_line = oldline; +} + CV * newXS(char *name, void (*subaddr) (CV *), char *filename) { @@ -3477,7 +3633,9 @@ newXS(char *name, void (*subaddr) (CV *), char *filename) } else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) { /* already defined (or promised) */ - if (dowarn) { + if (dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv)) + && HvNAME(GvSTASH(CvGV(cv))) + && strEQ(HvNAME(GvSTASH(CvGV(cv))), "autouse"))) { line_t oldline = curcop->cop_line; curcop->cop_line = copline; warn("Subroutine %s redefined",name); @@ -3569,7 +3727,7 @@ newFORM(I32 floor, OP *o, OP *block) CvGV(cv) = (GV*)SvREFCNT_inc(gv); CvFILEGV(cv) = curcop->cop_filegv; - for (ix = AvFILL(comppad); ix > 0; ix--) { + for (ix = AvFILLp(comppad); ix > 0; ix--) { if (!SvPADMY(curpad[ix]) && !SvIMMORTAL(curpad[ix])) SvPADTMP_on(curpad[ix]); } @@ -3702,8 +3860,10 @@ newSVREF(OP *o) o->op_ppaddr = ppaddr[OP_PADSV]; return o; } - else if (o->op_type == OP_THREADSV) + else if (o->op_type == OP_THREADSV && !(o->op_flags & OPpDONE_SVREF)) { + o->op_flags |= OPpDONE_SVREF; return o; + } return newUNOP(OP_RV2SV, 0, scalar(o)); } @@ -3834,10 +3994,12 @@ ck_eval(OP *o) enter->op_other = o; return o; } + else + scalar((OP*)kid); } else { op_free(o); - o = newUNOP(OP_ENTEREVAL, 0, newSVREF(newGVOP(OP_GV, 0, defgv))); + o = newUNOP(OP_ENTEREVAL, 0, newDEFSVOP()); } o->op_targ = (PADOFFSET)hints; return o; @@ -3911,17 +4073,16 @@ ck_rvconst(register OP *o) "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use", name, badthing); } - kid->op_type = OP_GV; + /* + * This is a little tricky. We only want to add the symbol if we + * didn't add it in the lexer. Otherwise we get duplicate strict + * warnings. But if we didn't add it in the lexer, we must at + * least pretend like we wanted to add it even if it existed before, + * or we get possible typo warnings. OPpCONST_ENTERED says + * whether the lexer already added THIS instance of this symbol. + */ iscv = (o->op_type == OP_RV2CV) * 2; - for (gv = 0; !gv; iscv++) { - /* - * This is a little tricky. We only want to add the symbol if we - * didn't add it in the lexer. Otherwise we get duplicate strict - * warnings. But if we didn't add it in the lexer, we must at - * least pretend like we wanted to add it even if it existed before, - * or we get possible typo warnings. OPpCONST_ENTERED says - * whether the lexer already added THIS instance of this symbol. - */ + do { gv = gv_fetchpv(name, iscv | !(kid->op_private & OPpCONST_ENTERED), iscv @@ -3933,9 +4094,12 @@ ck_rvconst(register OP *o) : o->op_type == OP_RV2HV ? SVt_PVHV : SVt_PVGV); + } while (!gv && !(kid->op_private & OPpCONST_ENTERED) && !iscv++); + if (gv) { + kid->op_type = OP_GV; + SvREFCNT_dec(kid->op_sv); + kid->op_sv = SvREFCNT_inc(gv); } - SvREFCNT_dec(kid->op_sv); - kid->op_sv = SvREFCNT_inc(gv); } return o; } @@ -3965,7 +4129,7 @@ ck_ftst(OP *o) return newGVOP(type, OPf_REF, gv_fetchpv("main::STDIN", TRUE, SVt_PVIO)); else - return newUNOP(type, 0, newSVREF(newGVOP(OP_GV, 0, defgv))); + return newUNOP(type, 0, newDEFSVOP()); } return o; } @@ -3998,7 +4162,7 @@ ck_fun(OP *o) kid = kid->op_sibling; } if (!kid && opargs[type] & OA_DEFGV) - *tokid = kid = newSVREF(newGVOP(OP_GV, 0, defgv)); + *tokid = kid = newDEFSVOP(); while (oa && kid) { numargs++; @@ -4096,7 +4260,7 @@ ck_fun(OP *o) } else if (opargs[type] & OA_DEFGV) { op_free(o); - return newUNOP(type, 0, newSVREF(newGVOP(OP_GV, 0, defgv))); + return newUNOP(type, 0, newDEFSVOP()); } if (oa) { @@ -4114,7 +4278,7 @@ ck_glob(OP *o) GV *gv; if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling) - append_elem(OP_GLOB, o, newSVREF(newGVOP(OP_GV, 0, defgv))); + append_elem(OP_GLOB, o, newDEFSVOP()); if (!((gv = gv_fetchpv("glob", FALSE, SVt_PVCV)) && GvIMPORTED_CV(gv))) gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV); @@ -4200,7 +4364,7 @@ ck_index(OP *o) if (o->op_flags & OPf_KIDS) { OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ if (kid && kid->op_type == OP_CONST) - fbm_compile(((SVOP*)kid)->op_sv); + fbm_compile(((SVOP*)kid)->op_sv, 0); } return ck_fun(o); } @@ -4251,7 +4415,7 @@ ck_listiob(OP *o) } if (!kid) - append_elem(o->op_type, o, newSVREF(newGVOP(OP_GV, 0, defgv)) ); + append_elem(o->op_type, o, newDEFSVOP()); o = listkids(o); @@ -4374,7 +4538,7 @@ ck_shift(OP *o) op_free(o); #ifdef USE_THREADS - if (subline) { + if (!CvUNIQUE(compcv)) { argop = newOP(OP_PADAV, OPf_REF); argop->op_targ = 0; /* curpad[0] is @_ */ } @@ -4385,7 +4549,7 @@ ck_shift(OP *o) } #else argop = newUNOP(OP_RV2AV, 0, - scalar(newGVOP(OP_GV, 0, subline ? + scalar(newGVOP(OP_GV, 0, !CvUNIQUE(compcv) ? defgv : gv_fetchpv("ARGV", TRUE, SVt_PVAV)))); #endif /* USE_THREADS */ return newUNOP(type, 0, scalar(argop)); @@ -4446,7 +4610,6 @@ OP * ck_split(OP *o) { register OP *kid; - PMOP* pm; if (o->op_flags & OPf_STACKED) return no_fh_allowed(o); @@ -4471,18 +4634,13 @@ ck_split(OP *o) cLISTOPo->op_first = kid; kid->op_sibling = sibl; } - pm = (PMOP*)kid; - if (pm->op_pmshort && !(pm->op_pmflags & PMf_ALL)) { - SvREFCNT_dec(pm->op_pmshort); /* can't use substring to optimize */ - pm->op_pmshort = 0; - } kid->op_type = OP_PUSHRE; kid->op_ppaddr = ppaddr[OP_PUSHRE]; scalar(kid); if (!kid->op_sibling) - append_elem(OP_SPLIT, o, newSVREF(newGVOP(OP_GV, 0, defgv)) ); + append_elem(OP_SPLIT, o, newDEFSVOP()); kid = kid->op_sibling; scalar(kid); @@ -4562,10 +4720,11 @@ ck_subr(OP *o) goto wrapref; { OP* kid = o2; - o2 = newUNOP(OP_RV2GV, 0, kid); - o2->op_sibling = kid->op_sibling; + OP* sib = kid->op_sibling; kid->op_sibling = 0; - prev->op_sibling = o; + o2 = newUNOP(OP_RV2GV, 0, kid); + o2->op_sibling = sib; + prev->op_sibling = o2; } goto wrapref; case '\\': @@ -4594,9 +4753,10 @@ ck_subr(OP *o) wrapref: { OP* kid = o2; - o2 = newUNOP(OP_REFGEN, 0, kid); - o2->op_sibling = kid->op_sibling; + OP* sib = kid->op_sibling; kid->op_sibling = 0; + o2 = newUNOP(OP_REFGEN, 0, kid); + o2->op_sibling = sib; prev->op_sibling = o2; } break; @@ -4691,7 +4851,7 @@ peep(register OP *o) goto nothin; case OP_NULL: if (o->op_targ == OP_NEXTSTATE || o->op_targ == OP_DBSTATE) - curcop = ((COP*)op); + curcop = ((COP*)o); goto nothin; case OP_SCALAR: case OP_LINESEQ: @@ -4764,6 +4924,8 @@ peep(register OP *o) case OP_AND: case OP_OR: o->op_seq = op_seqmax++; + while (cLOGOP->op_other->op_type == OP_NULL) + cLOGOP->op_other = cLOGOP->op_other->op_next; peep(cLOGOP->op_other); break; @@ -4790,6 +4952,8 @@ peep(register OP *o) o->op_seq = op_seqmax++; if (dowarn && o->op_next && o->op_next->op_type == OP_NEXTSTATE) { if (o->op_next->op_sibling && + o->op_next->op_sibling->op_type != OP_EXIT && + o->op_next->op_sibling->op_type != OP_WARN && o->op_next->op_sibling->op_type != OP_DIE) { line_t oldline = curcop->cop_line;