X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=eecde6766066e759e10a60f90a0a7d8e7855df5c;hb=3ed26a2c26e4f1468588c483e9e86eae4e74f24f;hp=b1f867feb08861a6dab68ba50cd75db2b74d0d48;hpb=b355b4e0798f66a89bbfedc23cbec69c1dff3d33;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index b1f867f..eecde67 100644 --- a/op.c +++ b/op.c @@ -18,54 +18,80 @@ #include "EXTERN.h" #include "perl.h" +#define USE_OP_MASK /* Turned on by default in 5.002beta1h */ + +#ifdef USE_OP_MASK +/* + * In the following definition, the ", (OP *) op" is just to make the compiler + * think the expression is of the right type: croak actually does a Siglongjmp. + */ +#define CHECKOP(type,op) \ + ((op_mask && op_mask[type]) \ + ? (croak("%s trapped by operation mask", op_desc[type]), (OP*)op) \ + : (*check[type])((OP*)op)) +#else +#define CHECKOP(type,op) (*check[type])(op) +#endif /* USE_OP_MASK */ + static I32 list_assignment _((OP *op)); -static OP *bad_type _((I32 n, char *t, OP *op, OP *kid)); +static OP *bad_type _((I32 n, char *t, char *name, OP *kid)); static OP *modkids _((OP *op, I32 type)); static OP *no_fh_allowed _((OP *op)); static OP *scalarboolean _((OP *op)); -static OP *too_few_arguments _((OP *op)); -static OP *too_many_arguments _((OP *op)); +static OP *too_few_arguments _((OP *op, char* name)); +static OP *too_many_arguments _((OP *op, char* name)); static void null _((OP* op)); -static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, I32 seq, +static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)); +static char* +CvNAME(cv) +CV* cv; +{ + SV* tmpsv = sv_newmortal(); + gv_efullname3(tmpsv, CvGV(cv), Nullch); + return SvPV(tmpsv,na); +} + static OP * no_fh_allowed(op) OP *op; { sprintf(tokenbuf,"Missing comma after first argument to %s function", - op_name[op->op_type]); + op_desc[op->op_type]); yyerror(tokenbuf); return op; } static OP * -too_few_arguments(op) -OP *op; +too_few_arguments(op, name) +OP* op; +char* name; { - sprintf(tokenbuf,"Not enough arguments for %s", op_name[op->op_type]); + sprintf(tokenbuf,"Not enough arguments for %s", name); yyerror(tokenbuf); return op; } static OP * -too_many_arguments(op) +too_many_arguments(op, name) OP *op; +char* name; { - sprintf(tokenbuf,"Too many arguments for %s", op_name[op->op_type]); + sprintf(tokenbuf,"Too many arguments for %s", name); yyerror(tokenbuf); return op; } static OP * -bad_type(n, t, op, kid) +bad_type(n, t, name, kid) I32 n; char *t; -OP *op; +char *name; OP *kid; { sprintf(tokenbuf, "Type of arg %d to %s must be %s (not %s)", - (int) n, op_name[op->op_type], t, op_name[kid->op_type]); + (int) n, name, t, op_desc[kid->op_type]); yyerror(tokenbuf); return op; } @@ -76,8 +102,7 @@ OP *op; { int type = op->op_type; if (type != OP_AELEM && type != OP_HELEM) { - sprintf(tokenbuf, "Can't use subscript on %s", - op_name[type]); + sprintf(tokenbuf, "Can't use subscript on %s", op_desc[type]); yyerror(tokenbuf); if (type == OP_RV2HV || type == OP_ENTERSUB) warn("(Did you mean $ or @ instead of %c?)\n", @@ -95,10 +120,23 @@ char *name; SV *sv; if (!(isALPHA(name[1]) || name[1] == '_' && (int)strlen(name) > 2)) { - if (!isprint(name[1])) - sprintf(name+1, "^%c", name[1] ^ 64); /* XXX is tokenbuf, really */ + if (!isPRINT(name[1])) + sprintf(name+1, "^%c", toCTRL(name[1])); /* XXX tokenbuf, really */ croak("Can't use global %s in \"my\"",name); } + if (AvFILL(comppad_name) >= 0) { + SV **svp = AvARRAY(comppad_name); + for (off = AvFILL(comppad_name); off > comppad_name_floor; off--) { + if ((sv = svp[off]) + && sv != &sv_undef + && SvIVX(sv) == 999999999 /* var is in open scope */ + && strEQ(name, SvPVX(sv))) + { + warn("\"my\" variable %s masks earlier declaration in same scope", name); + break; + } + } + } off = pad_alloc(OP_PADSV, SVs_PADMY); sv = NEWSV(1102,0); sv_upgrade(sv, SVt_PVNV); @@ -118,12 +156,16 @@ char *name; } static PADOFFSET +#ifndef CAN_PROTOTYPE pad_findlex(name, newoff, seq, startcv, cx_ix) char *name; PADOFFSET newoff; -I32 seq; +U32 seq; CV* startcv; I32 cx_ix; +#else +pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix) +#endif { CV *cv; I32 off; @@ -137,19 +179,28 @@ I32 cx_ix; SV** svp = av_fetch(curlist, 0, FALSE); AV *curname; if (!svp || *svp == &sv_undef) - break; + continue; curname = (AV*)*svp; svp = AvARRAY(curname); for (off = AvFILL(curname); off > 0; off--) { if ((sv = svp[off]) && sv != &sv_undef && seq <= SvIVX(sv) && - seq > (I32)SvNVX(sv) && + seq > I_32(SvNVX(sv)) && strEQ(SvPVX(sv), name)) { - I32 depth = CvDEPTH(cv) ? CvDEPTH(cv) : 1; - AV *oldpad = (AV*)*av_fetch(curlist, depth, FALSE); - SV *oldsv = *av_fetch(oldpad, off, TRUE); + I32 depth; + AV *oldpad; + SV *oldsv; + + depth = CvDEPTH(cv); + if (!depth) { + if (newoff && !CvUNIQUE(cv)) + return 0; /* don't clone inactive sub's stack frame */ + depth = 1; + } + oldpad = (AV*)*av_fetch(curlist, depth, FALSE); + oldsv = *av_fetch(oldpad, off, TRUE); if (!newoff) { /* Not a mere clone operation. */ SV *sv = NEWSV(1103,0); newoff = pad_alloc(OP_PADSV, SVs_PADMY); @@ -159,9 +210,19 @@ I32 cx_ix; SvNVX(sv) = (double)curcop->cop_seq; SvIVX(sv) = 999999999; /* A ref, intro immediately */ SvFLAGS(sv) |= SVf_FAKE; + if (!CvUNIQUE(cv)) { + /* "It's closures all the way down." */ + CvCLONE_on(compcv); + if (cv != startcv) { + CV *bcv; + for (bcv = startcv; + bcv && bcv != cv && !CvCLONE(bcv); + bcv = CvOUTSIDE(bcv)) + CvCLONE_on(bcv); + } + } } av_store(comppad, newoff, SvREFCNT_inc(oldsv)); - SvFLAGS(compcv) |= SVpcv_CLONE; return newoff; } } @@ -183,7 +244,8 @@ I32 cx_ix; } break; case CXt_EVAL: - if (cx->blk_eval.old_op_type != OP_ENTEREVAL) + if (cx->blk_eval.old_op_type != OP_ENTEREVAL && + cx->blk_eval.old_op_type != OP_ENTERTRY) return 0; /* require must have its own scope */ saweval = i; break; @@ -210,14 +272,14 @@ char *name; I32 off; SV *sv; SV **svp = AvARRAY(comppad_name); - I32 seq = cop_seqmax; + U32 seq = cop_seqmax; /* The one we're looking for is probably just before comppad_name_fill. */ - for (off = comppad_name_fill; off > 0; off--) { + for (off = AvFILL(comppad_name); off > 0; off--) { if ((sv = svp[off]) && sv != &sv_undef && seq <= SvIVX(sv) && - seq > (I32)SvNVX(sv) && + seq > I_32(SvNVX(sv)) && strEQ(SvPVX(sv), name)) { return (PADOFFSET)off; @@ -271,14 +333,26 @@ U32 tmptype; retval = AvFILL(comppad); } else { - do { - sv = *av_fetch(comppad, ++padix, TRUE); - } while (SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)); + SV **names = AvARRAY(comppad_name); + SSize_t names_fill = AvFILL(comppad_name); + for (;;) { + /* + * "foreach" index vars temporarily become aliases to non-"my" + * values. Thus we must skip, not just pad values that are + * marked as current pad values, but also those with names. + */ + if (++padix <= names_fill && + (sv = names[padix]) && sv != &sv_undef) + continue; + sv = *av_fetch(comppad, padix, TRUE); + if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY))) + break; + } retval = padix; } SvFLAGS(sv) |= tmptype; curpad = AvARRAY(comppad); - DEBUG_X(fprintf(stderr, "Pad alloc %ld for %s\n", (long) retval, op_name[optype])); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad alloc %ld for %s\n", (long) retval, op_name[optype])); return (PADOFFSET)retval; } @@ -292,7 +366,7 @@ pad_sv(PADOFFSET po) { if (!po) croak("panic: pad_sv po"); - DEBUG_X(fprintf(stderr, "Pad sv %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad sv %d\n", po)); return curpad[po]; /* eventually we'll turn this into a macro */ } @@ -310,7 +384,7 @@ pad_free(PADOFFSET po) croak("panic: pad_free curpad"); if (!po) croak("panic: pad_free po"); - DEBUG_X(fprintf(stderr, "Pad free %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad free %d\n", po)); if (curpad[po] && curpad[po] != &sv_undef) SvPADTMP_off(curpad[po]); if ((I32)po < padix) @@ -329,7 +403,7 @@ pad_swipe(PADOFFSET po) croak("panic: pad_swipe curpad"); if (!po) croak("panic: pad_swipe po"); - DEBUG_X(fprintf(stderr, "Pad swipe %d\n", po)); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %d\n", po)); SvPADTMP_off(curpad[po]); curpad[po] = NEWSV(1107,0); SvPADTMP_on(curpad[po]); @@ -344,7 +418,7 @@ pad_reset() if (AvARRAY(comppad) != curpad) croak("panic: pad_reset curpad"); - DEBUG_X(fprintf(stderr, "Pad reset\n")); + DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad reset\n")); if (!tainting) { /* Can't mix tainted and non-tainted temporaries. */ for (po = AvMAX(comppad); po > padix_floor; po--) { if (curpad[po] && curpad[po] != &sv_undef) @@ -363,7 +437,7 @@ OP *op; { register OP *kid, *nextkid; - if (!op) + if (!op || op->op_seq == (U16)-1) return; if (op->op_flags & OPf_KIDS) { @@ -386,6 +460,7 @@ OP *op; break; case OP_NEXTSTATE: case OP_DBSTATE: + Safefree(cCOP->cop_label); SvREFCNT_dec(cCOP->cop_filegv); break; case OP_CONST: @@ -406,7 +481,7 @@ OP *op; /* FALL THROUGH */ case OP_PUSHRE: case OP_MATCH: - regfree(cPMOP->op_pmregexp); + pregfree(cPMOP->op_pmregexp); SvREFCNT_dec(cPMOP->op_pmshort); break; default: @@ -494,7 +569,8 @@ OP *op; OP *kid; /* assumes no premature commitment */ - if (!op || (op->op_flags & OPf_KNOW) || error_count) + if (!op || (op->op_flags & OPf_KNOW) || op->op_type == OP_RETURN + || error_count) return op; op->op_flags &= ~OPf_LIST; @@ -502,6 +578,8 @@ OP *op; switch (op->op_type) { case OP_REPEAT: + if (op->op_private & OPpREPEAT_DOLIST) + null(((LISTOP*)cBINOP->op_first)->op_first); scalar(cBINOP->op_first); break; case OP_OR: @@ -563,6 +641,8 @@ OP *op; default: if (!(opargs[op->op_type] & OA_FOLDCONST)) break; + /* FALL THROUGH */ + case OP_REPEAT: if (op->op_flags & OPf_STACKED) break; /* FALL THROUGH */ @@ -574,7 +654,6 @@ OP *op; case OP_PADHV: case OP_PADANY: case OP_AV2ARYLEN: - case OP_SV2LEN: case OP_REF: case OP_REFGEN: case OP_SREFGEN: @@ -638,7 +717,7 @@ OP *op; case OP_GGRGID: case OP_GETLOGIN: if (!(op->op_private & OPpLVAL_INTRO)) - useless = op_name[op->op_type]; + useless = op_desc[op->op_type]; break; case OP_RV2GV: @@ -682,11 +761,6 @@ OP *op; op->op_ppaddr = ppaddr[OP_PREDEC]; break; - case OP_REPEAT: - scalarvoid(cBINOP->op_first); - useless = op_name[op->op_type]; - break; - case OP_OR: case OP_AND: case OP_COND_EXPR: @@ -747,7 +821,8 @@ OP *op; OP *kid; /* assumes no premature commitment */ - if (!op || (op->op_flags & OPf_KNOW) || error_count) + if (!op || (op->op_flags & OPf_KNOW) || op->op_type == OP_RETURN + || error_count) return op; op->op_flags |= (OPf_KNOW | OPf_LIST); @@ -844,7 +919,6 @@ I32 type; { OP *kid; SV *sv; - char mtype; if (!op || error_count) return op; @@ -866,6 +940,10 @@ I32 type; else croak("That use of $[ is unsupported"); break; + case OP_STUB: + if (op->op_flags & OPf_PARENS) + break; + goto nomod; case OP_ENTERSUB: if ((type == OP_UNDEF || type == OP_REFGEN) && !(op->op_flags & OPf_STACKED)) { @@ -882,8 +960,8 @@ I32 type; if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) break; sprintf(tokenbuf, "Can't modify %s in %s", - op_name[op->op_type], - type ? op_name[type] : "local"); + op_desc[op->op_type], + type ? op_desc[type] : "local"); yyerror(tokenbuf); return op; @@ -937,6 +1015,8 @@ I32 type; modcount = 10000; break; case OP_RV2SV: + if (!type && cUNOP->op_first->op_type != OP_GV) + croak("Can't localize a reference"); ref(cUNOP->op_first, op->op_type); /* FALL THROUGH */ case OP_UNDEF: @@ -950,6 +1030,8 @@ I32 type; case OP_PADAV: case OP_PADHV: modcount = 10000; + if (type == OP_REFGEN && op->op_flags & OPf_PARENS) + return op; /* Treat \(@foo) like ordinary list. */ /* FALL THROUGH */ case OP_PADSV: modcount++; @@ -961,23 +1043,18 @@ I32 type; case OP_PUSHMARK: break; + case OP_KEYS: + if (type != OP_SASSIGN) + goto nomod; + /* FALL THROUGH */ case OP_POS: - mtype = '.'; - goto makelv; case OP_VEC: - mtype = 'v'; - goto makelv; case OP_SUBSTR: - mtype = 'x'; - makelv: pad_free(op->op_targ); op->op_targ = pad_alloc(op->op_type, SVs_PADMY); - sv = PAD_SV(op->op_targ); - sv_upgrade(sv, SVt_PVLV); - sv_magic(sv, Nullsv, mtype, Nullch, 0); - curpad[op->op_targ] = sv; + assert(SvTYPE(PAD_SV(op->op_targ)) == SVt_NULL); if (op->op_flags & OPf_KIDS) - mod(cBINOP->op_first, type); + mod(cBINOP->op_first->op_sibling, type); break; case OP_AELEM: @@ -1050,6 +1127,7 @@ I32 type; op->op_ppaddr = ppaddr[OP_RV2CV]; assert(cUNOP->op_first->op_type == OP_NULL); null(((LISTOP*)cUNOP->op_first)->op_first); /* disable pushmark */ + op->op_flags |= OPf_SPECIAL; } break; @@ -1059,8 +1137,12 @@ I32 type; break; case OP_RV2SV: ref(cUNOP->op_first, op->op_type); - if (type == OP_RV2AV || type == OP_RV2HV) { - op->op_private |= (type == OP_RV2AV ? OPpDEREF_AV : OPpDEREF_HV); + /* FALL THROUGH */ + case OP_PADSV: + if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) { + op->op_private |= (type == OP_RV2AV ? OPpDEREF_AV + : type == OP_RV2HV ? OPpDEREF_HV + : OPpDEREF_SV); op->op_flags |= OPf_MOD; } break; @@ -1087,8 +1169,10 @@ I32 type; case OP_AELEM: case OP_HELEM: ref(cBINOP->op_first, op->op_type); - if (type == OP_RV2AV || type == OP_RV2HV) { - op->op_private |= (type == OP_RV2AV ? OPpDEREF_AV : OPpDEREF_HV); + if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) { + op->op_private |= (type == OP_RV2AV ? OPpDEREF_AV + : type == OP_RV2HV ? OPpDEREF_HV + : OPpDEREF_SV); op->op_flags |= OPf_MOD; } break; @@ -1128,7 +1212,7 @@ OP *op; type != OP_PADHV && type != OP_PUSHMARK) { - sprintf(tokenbuf, "Can't declare %s in my", op_name[op->op_type]); + sprintf(tokenbuf, "Can't declare %s in my", op_desc[op->op_type]); yyerror(tokenbuf); return op; } @@ -1188,7 +1272,7 @@ scope(o) OP *o; { if (o) { - if (o->op_flags & OPf_PARENS || perldb) { + if (o->op_flags & OPf_PARENS || perldb || tainting) { o = prepend_elem(OP_LINESEQ, newOP(OP_ENTER, 0), o); o->op_type = OP_LEAVE; o->op_ppaddr = ppaddr[OP_LEAVE]; @@ -1212,37 +1296,42 @@ OP *o; } int -block_start() +block_start(full) +int full; { int retval = savestack_ix; - comppad_name_fill = AvFILL(comppad_name); - SAVEINT(min_intro_pending); - SAVEINT(max_intro_pending); + SAVEI32(comppad_name_floor); + if (full) { + if ((comppad_name_fill = AvFILL(comppad_name)) > 0) + comppad_name_floor = comppad_name_fill; + else + comppad_name_floor = 0; + } + SAVEI32(min_intro_pending); + SAVEI32(max_intro_pending); min_intro_pending = 0; - SAVEINT(comppad_name_fill); - SAVEINT(padix_floor); + SAVEI32(comppad_name_fill); + SAVEI32(padix_floor); padix_floor = padix; pad_reset_pending = FALSE; - SAVEINT(hints); + SAVEI32(hints); hints &= ~HINT_BLOCK_SCOPE; return retval; } OP* -block_end(line, floor, seq) -int line; -int floor; +block_end(floor, seq) +I32 floor; OP* seq; { int needblockscope = hints & HINT_BLOCK_SCOPE; OP* retval = scalarseq(seq); - if (copline > (line_t)line) - copline = line; LEAVE_SCOPE(floor); pad_reset_pending = FALSE; if (needblockscope) hints |= HINT_BLOCK_SCOPE; /* propagate out */ pad_leavemy(comppad_name_fill); + cop_seqmax++; return retval; } @@ -1251,7 +1340,7 @@ newPROG(op) OP *op; { if (in_eval) { - eval_root = newUNOP(OP_LEAVEEVAL, 0, op); + eval_root = newUNOP(OP_LEAVEEVAL, ((in_eval & 4) ? OPf_SPECIAL : 0), op); eval_start = linklist(eval_root); eval_root->op_next = 0; peep(eval_start); @@ -1342,7 +1431,7 @@ register OP *o; curop = LINKLIST(o); o->op_next = 0; op = curop; - run(); + runops(); sv = *(stack_sp--); if (o->op_targ && sv == PAD_SV(o->op_targ)) /* grab pad temp? */ pad_swipe(o->op_targ); @@ -1352,7 +1441,7 @@ register OP *o; } op_free(o); if (type == OP_RV2GV) - return newGVOP(OP_GV, 0, sv); + return newGVOP(OP_GV, 0, (GV*)sv); else { if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK) { IV iv = SvIV(sv); @@ -1360,6 +1449,8 @@ register OP *o; SvREFCNT_dec(sv); sv = newSViv(iv); } + else + SvIOK_off(sv); /* undo SvIV() damage */ } return newSVOP(OP_CONST, 0, sv); } @@ -1402,7 +1493,7 @@ register OP *o; op = curop = LINKLIST(o); o->op_next = 0; pp_pushmark(); - run(); + runops(); op = curop; pp_anonlist(); tmps_floor = oldtmps_floor; @@ -1437,7 +1528,7 @@ OP* op; op->op_ppaddr = ppaddr[type]; op->op_flags |= flags; - op = (*check[type])(op); + op = CHECKOP(type, op); if (op->op_type != type) return op; @@ -1608,12 +1699,12 @@ I32 flags; op->op_flags = flags; op->op_next = op; - /* op->op_private = 0; */ + op->op_private = 0 + (flags >> 8); if (opargs[type] & OA_RETSCALAR) scalar(op); if (opargs[type] & OA_TARGET) op->op_targ = pad_alloc(type, SVs_PADTMP); - return (*check[type])(op); + return CHECKOP(type, op); } OP * @@ -1634,9 +1725,9 @@ OP* first; unop->op_ppaddr = ppaddr[type]; unop->op_first = first; unop->op_flags = flags | OPf_KIDS; - unop->op_private = 1; + unop->op_private = 1 | (flags >> 8); - unop = (UNOP*)(*check[type])((OP*)unop); + unop = (UNOP*) CHECKOP(type, unop); if (unop->op_next) return (OP*)unop; @@ -1662,14 +1753,14 @@ OP* last; binop->op_flags = flags | OPf_KIDS; if (!last) { last = first; - binop->op_private = 1; + binop->op_private = 1 | (flags >> 8); } else { - binop->op_private = 2; + binop->op_private = 2 | (flags >> 8); first->op_sibling = last; } - binop = (BINOP*)(*check[type])((OP*)binop); + binop = (BINOP*)CHECKOP(type, binop); if (binop->op_next) return (OP*)binop; @@ -1688,8 +1779,8 @@ OP *repl; SV *rstr = ((SVOP*)repl)->op_sv; STRLEN tlen; STRLEN rlen; - register char *t = SvPV(tstr, tlen); - register char *r = SvPV(rstr, rlen); + register U8 *t = (U8*)SvPV(tstr, tlen); + register U8 *r = (U8*)SvPV(rstr, rlen); register I32 i; register I32 j; I32 delete; @@ -1704,19 +1795,19 @@ OP *repl; if (complement) { Zero(tbl, 256, short); for (i = 0; i < tlen; i++) - tbl[t[i] & 0377] = -1; + tbl[t[i]] = -1; for (i = 0, j = 0; i < 256; i++) { if (!tbl[i]) { if (j >= rlen) { if (delete) tbl[i] = -2; else if (rlen) - tbl[i] = r[j-1] & 0377; + tbl[i] = r[j-1]; else tbl[i] = i; } else - tbl[i] = r[j++] & 0377; + tbl[i] = r[j++]; } } } @@ -1729,14 +1820,14 @@ OP *repl; for (i = 0, j = 0; i < tlen; i++,j++) { if (j >= rlen) { if (delete) { - if (tbl[t[i] & 0377] == -1) - tbl[t[i] & 0377] = -2; + if (tbl[t[i]] == -1) + tbl[t[i]] = -2; continue; } --j; } - if (tbl[t[i] & 0377] == -1) - tbl[t[i] & 0377] = r[j] & 0377; + if (tbl[t[i]] == -1) + tbl[t[i]] = r[j]; } } op_free(expr); @@ -1756,7 +1847,10 @@ I32 flags; pmop->op_type = type; pmop->op_ppaddr = ppaddr[type]; pmop->op_flags = flags; - pmop->op_private = 0; + pmop->op_private = 0 | (flags >> 8); + + if (hints & HINT_LOCALE) + pmop->op_pmpermflags = (pmop->op_pmflags |= PMf_LOCALE); /* link into pm list */ if (type != OP_TRANS && curstash) { @@ -1790,7 +1884,7 @@ OP *repl; p = SvPV(pat, plen); pm->op_pmflags |= PMf_SKIPWHITE; } - pm->op_pmregexp = regcomp(p, p + plen, pm); + pm->op_pmregexp = pregcomp(p, p + plen, pm); if (strEQ("\\s+", pm->op_pmregexp->precomp)) pm->op_pmflags |= PMf_WHITE; hoistmust(pm); @@ -1860,6 +1954,7 @@ OP *repl; } if (curop == repl) { pm->op_pmflags |= PMf_CONST; /* const for long enough */ + pm->op_pmpermflags |= PMf_CONST; /* const for long enough */ prepend_elem(op->op_type, scalar(repl), op); } else { @@ -1901,7 +1996,7 @@ SV *sv; scalar((OP*)svop); if (opargs[type] & OA_TARGET) svop->op_targ = pad_alloc(type, SVs_PADTMP); - return (*check[type])((OP*)svop); + return CHECKOP(type, svop); } OP * @@ -1921,7 +2016,7 @@ GV *gv; scalar((OP*)gvop); if (opargs[type] & OA_TARGET) gvop->op_targ = pad_alloc(type, SVs_PADTMP); - return (*check[type])((OP*)gvop); + return CHECKOP(type, gvop); } OP * @@ -1941,29 +2036,7 @@ char *pv; scalar((OP*)pvop); if (opargs[type] & OA_TARGET) pvop->op_targ = pad_alloc(type, SVs_PADTMP); - return (*check[type])((OP*)pvop); -} - -OP * -newCVOP(type, flags, cv, cont) -I32 type; -I32 flags; -CV *cv; -OP *cont; -{ - CVOP *cvop; - Newz(1101, cvop, 1, CVOP); - cvop->op_type = type; - cvop->op_ppaddr = ppaddr[type]; - cvop->op_cv = cv; - cvop->op_cont = cont; - cvop->op_next = (OP*)cvop; - cvop->op_flags = flags; - if (opargs[type] & OA_RETSCALAR) - scalar((OP*)cvop); - if (opargs[type] & OA_TARGET) - cvop->op_targ = pad_alloc(type, SVs_PADTMP); - return (*check[type])((OP*)cvop); + return CHECKOP(type, pvop); } void @@ -1979,7 +2052,7 @@ OP *op; char *name; sv = cSVOP->op_sv; name = SvPV(sv, len); - curstash = gv_stashpv(name,TRUE); + curstash = gv_stashpvn(name,len,TRUE); sv_setpvn(curstname, name, len); op_free(op); } @@ -1992,8 +2065,10 @@ OP *op; } void -utilize(aver, id, arg) +utilize(aver, floor, version, id, arg) int aver; +I32 floor; +OP *version; OP *id; OP *arg; { @@ -2001,33 +2076,69 @@ OP *arg; OP *meth; OP *rqop; OP *imop; + OP *veop; if (id->op_type != OP_CONST) croak("Module name must be constant"); - meth = newSVOP(OP_CONST, 0, - aver - ? newSVpv("import", 6) - : newSVpv("unimport", 8) - ); + veop = Nullop; - /* Make copy of id so we don't free it twice */ - pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv)); + if(version != Nullop) { + SV *vesv = ((SVOP*)version)->op_sv; - /* Fake up a require */ - rqop = newUNOP(OP_REQUIRE, 0, id); + if (arg == Nullop && !SvNIOK(vesv)) { + arg = version; + } + else { + OP *pack; + OP *meth; + + if (version->op_type != OP_CONST || !SvNIOK(vesv)) + croak("Version number must be constant number"); + + /* Make copy of id so we don't free it twice */ + pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv)); + /* Fake up a method call to VERSION */ + meth = newSVOP(OP_CONST, 0, newSVpv("VERSION", 7)); + veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, + append_elem(OP_LIST, + prepend_elem(OP_LIST, pack, list(version)), + newUNOP(OP_METHOD, 0, meth))); + } + } + /* Fake up an import/unimport */ - imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, + if (arg && arg->op_type == OP_STUB) + imop = arg; /* no import on explicit () */ + else if(SvNIOK(((SVOP*)id)->op_sv)) { + imop = Nullop; /* use 5.0; */ + } + else { + /* Make copy of id so we don't free it twice */ + pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv)); + meth = newSVOP(OP_CONST, 0, + aver + ? newSVpv("import", 6) + : newSVpv("unimport", 8) + ); + imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), newUNOP(OP_METHOD, 0, meth))); + } + + /* Fake up a require */ + rqop = newUNOP(OP_REQUIRE, 0, id); /* Fake up the BEGIN {}, which does its thing immediately. */ - newSUB(start_subparse(), + newSUB(floor, newSVOP(OP_CONST, 0, newSVpv("BEGIN", 5)), + Nullop, append_elem(OP_LINESEQ, - newSTATEOP(0, Nullch, rqop), + append_elem(OP_LINESEQ, + newSTATEOP(0, Nullch, rqop), + newSTATEOP(0, Nullch, veop)), newSTATEOP(0, Nullch, imop) )); copline = NOLINE; @@ -2112,33 +2223,10 @@ OP *right; op_free(right); return Nullop; } - if (right && right->op_type == OP_SPLIT) { - if ((op = ((LISTOP*)right)->op_first) && op->op_type == OP_PUSHRE) { - PMOP *pm = (PMOP*)op; - if (left->op_type == OP_RV2AV && - !(left->op_private & OPpLVAL_INTRO) ) - { - op = ((UNOP*)left)->op_first; - if (op->op_type == OP_GV && !pm->op_pmreplroot) { - pm->op_pmreplroot = (OP*)((GVOP*)op)->op_gv; - pm->op_pmflags |= PMf_ONCE; - op_free(left); - return right; - } - } - else { - if (modcount < 10000) { - SV *sv = ((SVOP*)((LISTOP*)right)->op_last)->op_sv; - if (SvIVX(sv) == 0) - sv_setiv(sv, modcount+1); - } - } - } - } op = newBINOP(OP_AASSIGN, flags, list(force_list(right)), list(force_list(left)) ); - op->op_private = 0; + op->op_private = 0 | (flags >> 8); if (!(left->op_private & OPpLVAL_INTRO)) { static int generation = 100; OP *curop; @@ -2157,7 +2245,7 @@ OP *right; curop->op_type == OP_PADHV || curop->op_type == OP_PADANY) { SV **svp = AvARRAY(comppad_name); - SV *sv = svp[curop->op_targ];; + SV *sv = svp[curop->op_targ]; if (SvCUR(sv) == generation) break; SvCUR(sv) = generation; /* (SvCUR not used any more) */ @@ -2179,6 +2267,41 @@ OP *right; if (curop != op) op->op_private = OPpASSIGN_COMMON; } + if (right && right->op_type == OP_SPLIT) { + OP* tmpop; + if ((tmpop = ((LISTOP*)right)->op_first) && + tmpop->op_type == OP_PUSHRE) + { + PMOP *pm = (PMOP*)tmpop; + if (left->op_type == OP_RV2AV && + !(left->op_private & OPpLVAL_INTRO) && + !(op->op_private & OPpASSIGN_COMMON) ) + { + tmpop = ((UNOP*)left)->op_first; + if (tmpop->op_type == OP_GV && !pm->op_pmreplroot) { + pm->op_pmreplroot = (OP*)((GVOP*)tmpop)->op_gv; + pm->op_pmflags |= PMf_ONCE; + tmpop = ((UNOP*)op)->op_first; /* to list (nulled) */ + tmpop = ((UNOP*)tmpop)->op_first; /* to pushmark */ + tmpop->op_sibling = Nullop; /* don't free split */ + right->op_next = tmpop->op_next; /* fix starting loc */ + op_free(op); /* blow off assign */ + right->op_flags &= ~(OPf_KNOW|OPf_LIST); + /* "I don't know and I don't care." */ + return right; + } + } + else { + if (modcount < 10000 && + ((LISTOP*)right)->op_last->op_type == OP_CONST) + { + SV *sv = ((SVOP*)((LISTOP*)right)->op_last)->op_sv; + if (SvIVX(sv) == 0) + sv_setiv(sv, modcount+1); + } + } + } + } return op; } if (!right) @@ -2207,22 +2330,9 @@ I32 flags; char *label; OP *op; { + U32 seq = intro_my(); register COP *cop; - /* Introduce my variables. */ - if (min_intro_pending) { - SV **svp = AvARRAY(comppad_name); - I32 i; - SV *sv; - for (i = min_intro_pending; i <= max_intro_pending; i++) { - if ((sv = svp[i]) && sv != &sv_undef) - SvIVX(sv) = 999999999; /* Don't know scope end yet. */ - SvNVX(sv) = (double)cop_seqmax; - } - min_intro_pending = 0; - comppad_name_fill = max_intro_pending; /* Needn't search higher */ - } - Newz(1101, cop, 1, COP); if (perldb && curcop->cop_line && curstash != debstash) { cop->op_type = OP_DBSTATE; @@ -2233,14 +2343,14 @@ OP *op; cop->op_ppaddr = ppaddr[ OP_NEXTSTATE ]; } cop->op_flags = flags; - cop->op_private = 0; + cop->op_private = 0 | (flags >> 8); cop->op_next = (OP*)cop; if (label) { cop->cop_label = label; hints |= HINT_BLOCK_SCOPE; } - cop->cop_seq = cop_seqmax++; + cop->cop_seq = seq; cop->cop_arybase = curcop->cop_arybase; if (copline == NOLINE) @@ -2249,14 +2359,14 @@ OP *op; cop->cop_line = copline; copline = NOLINE; } - cop->cop_filegv = SvREFCNT_inc(curcop->cop_filegv); + cop->cop_filegv = GvREFCNT_inc(curcop->cop_filegv); cop->cop_stash = curstash; if (perldb && curstash != debstash) { SV **svp = av_fetch(GvAV(curcop->cop_filegv),(I32)cop->cop_line, FALSE); if (svp && *svp != &sv_undef && !SvIOK(*svp)) { - SvIVX(*svp) = 1; (void)SvIOK_on(*svp); + SvIVX(*svp) = 1; SvSTASH(*svp) = (HV*)cop; } } @@ -2264,6 +2374,29 @@ OP *op; return prepend_elem(OP_LINESEQ, (OP*)cop, op); } +/* "Introduce" my variables to visible status. */ +U32 +intro_my() +{ + SV **svp; + SV *sv; + I32 i; + + if (! min_intro_pending) + return cop_seqmax; + + svp = AvARRAY(comppad_name); + for (i = min_intro_pending; i <= max_intro_pending; i++) { + if ((sv = svp[i]) && sv != &sv_undef && !SvIVX(sv)) { + SvIVX(sv) = 999999999; /* Don't know scope end yet. */ + SvNVX(sv) = (double)cop_seqmax; + } + } + min_intro_pending = 0; + comppad_name_fill = max_intro_pending; /* Needn't search higher */ + return cop_seqmax++; +} + OP * newLOGOP(type, flags, first, other) I32 type; @@ -2295,7 +2428,7 @@ OP* other; } if (first->op_type == OP_CONST) { if (dowarn && (first->op_private & OPpCONST_BARE)) - warn("Probable precedence problem on %s", op_name[type]); + warn("Probable precedence problem on %s", op_desc[type]); if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) { op_free(first); return other; @@ -2325,7 +2458,7 @@ OP* other; logop->op_first = first; logop->op_flags = flags | OPf_KIDS; logop->op_other = LINKLIST(other); - logop->op_private = 1; + logop->op_private = 1 | (flags >> 8); /* establish postfix order */ logop->op_next = LINKLIST(first); @@ -2339,36 +2472,36 @@ OP* other; } OP * -newCONDOP(flags, first, true, false) +newCONDOP(flags, first, trueop, falseop) I32 flags; OP* first; -OP* true; -OP* false; +OP* trueop; +OP* falseop; { CONDOP *condop; OP *op; - if (!false) - return newLOGOP(OP_AND, 0, first, true); - if (!true) - return newLOGOP(OP_OR, 0, first, false); + if (!falseop) + return newLOGOP(OP_AND, 0, first, trueop); + if (!trueop) + return newLOGOP(OP_OR, 0, first, falseop); scalarboolean(first); if (first->op_type == OP_CONST) { if (SvTRUE(((SVOP*)first)->op_sv)) { op_free(first); - op_free(false); - return true; + op_free(falseop); + return trueop; } else { op_free(first); - op_free(true); - return false; + op_free(trueop); + return falseop; } } else if (first->op_type == OP_WANTARRAY) { - list(true); - scalar(false); + list(trueop); + scalar(falseop); } Newz(1101, condop, 1, CONDOP); @@ -2376,20 +2509,20 @@ OP* false; condop->op_ppaddr = ppaddr[OP_COND_EXPR]; condop->op_first = first; condop->op_flags = flags | OPf_KIDS; - condop->op_true = LINKLIST(true); - condop->op_false = LINKLIST(false); - condop->op_private = 1; + condop->op_true = LINKLIST(trueop); + condop->op_false = LINKLIST(falseop); + condop->op_private = 1 | (flags >> 8); /* establish postfix order */ condop->op_next = LINKLIST(first); first->op_next = (OP*)condop; - first->op_sibling = true; - true->op_sibling = false; + first->op_sibling = trueop; + trueop->op_sibling = falseop; op = newUNOP(OP_NULL, 0, (OP*)condop); - true->op_next = op; - false->op_next = op; + trueop->op_next = op; + falseop->op_next = op; return op; } @@ -2413,7 +2546,7 @@ OP *right; condop->op_flags = OPf_KIDS; condop->op_true = LINKLIST(left); condop->op_false = LINKLIST(right); - condop->op_private = 1; + condop->op_private = 1 | (flags >> 8); left->op_sibling = right; @@ -2542,6 +2675,7 @@ OP *cont; loop->op_nextop = op; op->op_flags |= flags; + op->op_private |= (flags >> 8); return op; } @@ -2561,6 +2695,7 @@ newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont { LOOP *loop; int padoff = 0; + I32 iterflags = 0; copline = forline; if (sv) { @@ -2574,12 +2709,16 @@ newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont sv = Nullop; } else - croak("Can't use %s for loop variable", op_name[sv->op_type]); + croak("Can't use %s for loop variable", op_desc[sv->op_type]); } else { sv = newGVOP(OP_GV, 0, defgv); } - loop = (LOOP*)list(convert(OP_ENTERITER, 0, + if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) { + expr = scalar(ref(expr, OP_ITER)); + iterflags |= OPf_STACKED; + } + loop = (LOOP*)list(convert(OP_ENTERITER, iterflags, append_elem(OP_LIST, mod(force_list(expr), OP_GREPSTART), scalar(sv)))); assert(!loop->op_next); @@ -2623,38 +2762,80 @@ CV *cv; SAVESPTR(curpad); curpad = 0; - if (!SvFLAGS(cv) & SVpcv_CLONED) + if (!CvCLONED(cv)) op_free(CvROOT(cv)); CvROOT(cv) = Nullop; - if (CvPADLIST(cv)) { - I32 i = AvFILL(CvPADLIST(cv)); - while (i >= 0) { - SV** svp = av_fetch(CvPADLIST(cv), i--, FALSE); - if (svp) - SvREFCNT_dec(*svp); - } - SvREFCNT_dec((SV*)CvPADLIST(cv)); - CvPADLIST(cv) = Nullav; - } - SvREFCNT_dec(CvGV(cv)); - CvGV(cv) = Nullgv; LEAVE; } + SvREFCNT_dec(CvGV(cv)); + CvGV(cv) = Nullgv; + SvREFCNT_dec(CvOUTSIDE(cv)); + CvOUTSIDE(cv) = Nullcv; + if (CvPADLIST(cv)) { + I32 i = AvFILL(CvPADLIST(cv)); + while (i >= 0) { + SV** svp = av_fetch(CvPADLIST(cv), i--, FALSE); + if (svp) + SvREFCNT_dec(*svp); + } + SvREFCNT_dec((SV*)CvPADLIST(cv)); + CvPADLIST(cv) = Nullav; + } } -CV * -cv_clone(proto) +#ifdef DEBUG_CLOSURES +static void +cv_dump(cv) +CV* cv; +{ + CV *outside = CvOUTSIDE(cv); + AV* padlist = CvPADLIST(cv); + AV* pad_name = (AV*)*av_fetch(padlist, 0, FALSE); + AV* pad = (AV*)*av_fetch(padlist, 1, FALSE); + SV** pname = AvARRAY(pad_name); + SV** ppad = AvARRAY(pad); + I32 ix; + + PerlIO_printf(Perl_debug_log, "\tCV=0x%p (%s), OUTSIDE=0x%p (%s)\n", + cv, + (CvANON(cv) ? "ANON" + : (cv == main_cv) ? "MAIN" + : CvUNIQUE(outside) ? "UNIQUE" + : CvGV(cv) ? GvNAME(CvGV(cv)) : "?mystery?"), + outside, + (!outside ? "null" + : CvANON(outside) ? "ANON" + : (outside == main_cv) ? "MAIN" + : CvUNIQUE(outside) ? "UNIQUE" + : CvGV(outside) ? GvNAME(CvGV(outside)) : "?mystery?")); + + for (ix = 1; ix <= AvFILL(pad); ix++) { + if (SvPOK(pname[ix])) + PerlIO_printf(Perl_debug_log, "\t%4d. 0x%p (\"%s\" %ld-%ld)\n", + ix, ppad[ix], SvPVX(pname[ix]), + (long)I_32(SvNVX(pname[ix])), + (long)SvIVX(pname[ix])); + } +} +#endif /* DEBUG_CLOSURES */ + +static CV * +cv_clone2(proto, outside) CV* proto; +CV* outside; { AV* av; I32 ix; AV* protopadlist = CvPADLIST(proto); AV* protopad_name = (AV*)*av_fetch(protopadlist, 0, FALSE); AV* protopad = (AV*)*av_fetch(protopadlist, 1, FALSE); - SV** svp = AvARRAY(protopad); + SV** pname = AvARRAY(protopad_name); + SV** ppad = AvARRAY(protopad); AV* comppadlist; CV* cv; + assert(!CvUNIQUE(proto)); + ENTER; SAVESPTR(curpad); SAVESPTR(comppad); @@ -2662,14 +2843,17 @@ CV* proto; cv = compcv = (CV*)NEWSV(1104,0); sv_upgrade((SV *)cv, SVt_PVCV); - SvFLAGS(cv) |= SVpcv_CLONED; + CvCLONED_on(cv); + if (CvANON(proto)) + CvANON_on(cv); CvFILEGV(cv) = CvFILEGV(proto); - CvGV(cv) = SvREFCNT_inc(CvGV(proto)); + CvGV(cv) = GvREFCNT_inc(CvGV(proto)); CvSTASH(cv) = CvSTASH(proto); CvROOT(cv) = CvROOT(proto); CvSTART(cv) = CvSTART(proto); - CvOUTSIDE(cv) = CvOUTSIDE(proto); + if (outside) + CvOUTSIDE(cv) = (CV*)SvREFCNT_inc(outside); comppad = newAV(); @@ -2678,7 +2862,7 @@ CV* proto; av_store(comppadlist, 0, SvREFCNT_inc((SV*)protopad_name)); av_store(comppadlist, 1, (SV*)comppad); CvPADLIST(cv) = comppadlist; - av_extend(comppad, AvFILL(protopad)); + av_fill(comppad, AvFILL(protopad)); curpad = AvARRAY(comppad); av = newAV(); /* will be @_ */ @@ -2686,45 +2870,111 @@ CV* proto; av_store(comppad, 0, (SV*)av); AvFLAGS(av) = AVf_REIFY; - svp = AvARRAY(protopad_name); - for ( ix = AvFILL(protopad); ix > 0; ix--) { - SV *sv; - if (svp[ix] != &sv_undef) { - char *name = SvPVX(svp[ix]); /* XXX */ - if (SvFLAGS(svp[ix]) & SVf_FAKE) { /* lexical from outside? */ - I32 off = pad_findlex(name,ix,curcop->cop_seq, CvOUTSIDE(proto), cxstack_ix); - if (off != ix) + for (ix = AvFILL(protopad); ix > 0; ix--) { + SV* sv; + if (pname[ix] != &sv_undef) { + char *name = SvPVX(pname[ix]); /* XXX */ + if (SvFLAGS(pname[ix]) & SVf_FAKE) { /* lexical from outside? */ + I32 off = pad_findlex(name, ix, SvIVX(pname[ix]), + CvOUTSIDE(cv), cxstack_ix); + if (!off) + curpad[ix] = SvREFCNT_inc(ppad[ix]); + else if (off != ix) croak("panic: cv_clone: %s", name); } else { /* our own lexical */ - if (*name == '@') - av_store(comppad, ix, sv = (SV*)newAV()); + if (*name == '&') { + /* anon code -- we'll come back for it */ + sv = SvREFCNT_inc(ppad[ix]); + } + else if (*name == '@') + sv = (SV*)newAV(); else if (*name == '%') - av_store(comppad, ix, sv = (SV*)newHV()); + sv = (SV*)newHV(); else - av_store(comppad, ix, sv = NEWSV(0,0)); - SvPADMY_on(sv); + sv = NEWSV(0,0); + if (!SvPADBUSY(sv)) + SvPADMY_on(sv); + curpad[ix] = sv; } } else { - av_store(comppad, ix, sv = NEWSV(0,0)); + sv = NEWSV(0,0); SvPADTMP_on(sv); + curpad[ix] = sv; } } + /* Now that vars are all in place, clone nested closures. */ + + for (ix = AvFILL(protopad); ix > 0; ix--) { + if (pname[ix] != &sv_undef + && !(SvFLAGS(pname[ix]) & SVf_FAKE) + && *SvPVX(pname[ix]) == '&' + && CvCLONE(ppad[ix])) + { + CV *kid = cv_clone2((CV*)ppad[ix], cv); + SvREFCNT_dec(ppad[ix]); + CvCLONE_on(kid); + SvPADMY_on(kid); + curpad[ix] = (SV*)kid; + } + } + +#ifdef DEBUG_CLOSURES + PerlIO_printf(Perl_debug_log, "Cloned inside:\n"); + cv_dump(outside); + PerlIO_printf(Perl_debug_log, " from:\n"); + cv_dump(proto); + PerlIO_printf(Perl_debug_log, " to:\n"); + cv_dump(cv); +#endif + LEAVE; return cv; } CV * -newSUB(floor,op,block) +cv_clone(proto) +CV* proto; +{ + return cv_clone2(proto, CvOUTSIDE(proto)); +} + +SV * +cv_const_sv(cv) +CV *cv; +{ + OP *o; + SV *sv = Nullsv; + + if(cv && SvPOK(cv) && !SvCUR(cv)) { + for (o = CvSTART(cv); o; o = o->op_next) { + OPCODE type = o->op_type; + + if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK) + continue; + if (type == OP_LEAVESUB || type == OP_RETURN) + break; + if (type != OP_CONST || sv) + return Nullsv; + + sv = ((SVOP*)o)->op_sv; + } + } + return sv; +} + +CV * +newSUB(floor,op,proto,block) I32 floor; OP *op; +OP *proto; OP *block; { register CV *cv; char *name = op ? SvPVx(cSVOP->op_sv, na) : "__ANON__"; - GV *gv = gv_fetchpv(name, GV_ADDMULTI, SVt_PVCV); + GV* gv = gv_fetchpv(name, GV_ADDMULTI, SVt_PVCV); AV* av; char *s; I32 ix; @@ -2734,12 +2984,23 @@ OP *block; if (cv = GvCV(gv)) { if (GvCVGEN(gv)) cv = 0; /* just a cached method */ - else if (CvROOT(cv) || CvXSUB(cv) || GvFLAGS(gv) & GVf_IMPORTED) { - if (dowarn) { /* already defined (or promised)? */ + else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) { + SV* const_sv = cv_const_sv(cv); + + char *p = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch; + + if((!proto != !SvPOK(cv)) || (p && strNE(SvPV((SV*)cv,na), p))) { + warn("Prototype mismatch: (%s) vs (%s)", + SvPOK(cv) ? SvPV((SV*)cv,na) : "none", + p ? p : "none"); + } + + if ((const_sv || dowarn) && strNE(name, "BEGIN")) {/* already defined (or promised)? */ line_t oldline = curcop->cop_line; curcop->cop_line = copline; - warn("Subroutine %s redefined",name); + warn(const_sv ? "Constant subroutine %s redefined" + : "Subroutine %s redefined",name); curcop->cop_line = oldline; } SvREFCNT_dec(cv); @@ -2747,12 +3008,13 @@ OP *block; } } if (cv) { /* must reuse cv if autoloaded */ - if (CvGV(cv)) { - assert(SvREFCNT(CvGV(cv)) > 1); - SvREFCNT_dec(CvGV(cv)); - } + cv_undef(cv); CvOUTSIDE(cv) = CvOUTSIDE(compcv); + CvOUTSIDE(compcv) = 0; CvPADLIST(cv) = CvPADLIST(compcv); + CvPADLIST(compcv) = 0; + if (SvREFCNT(compcv) > 1) /* XXX Make closures transit through stub. */ + CvOUTSIDE(compcv) = (CV*)SvREFCNT_inc((SV*)cv); SvREFCNT_dec(compcv); } else { @@ -2761,9 +3023,19 @@ OP *block; GvCV(gv) = cv; GvCVGEN(gv) = 0; CvFILEGV(cv) = curcop->cop_filegv; - CvGV(cv) = SvREFCNT_inc(gv); + CvGV(cv) = GvREFCNT_inc(gv); CvSTASH(cv) = curstash; + if (proto) { + char *p = SvPVx(((SVOP*)proto)->op_sv, na); + sv_setpv((SV*)cv, p); + op_free(proto); + } + + if (error_count) { + op_free(block); + block = Nullop; + } if (!block) { CvROOT(cv) = 0; op_free(op); @@ -2793,8 +3065,9 @@ OP *block; s++; else s = name; - if (strEQ(s, "BEGIN")) { + if (strEQ(s, "BEGIN") && !error_count) { line_t oldline = compiling.cop_line; + SV *oldrs = rs; ENTER; SAVESPTR(compiling.cop_filegv); @@ -2803,21 +3076,20 @@ OP *block; beginav = newAV(); av_push(beginav, (SV *)cv); DEBUG_x( dump_sub(gv) ); - rs = nrs; - rslen = nrslen; - rschar = nrschar; - rspara = (nrslen == 2); - GvCV(gv) = 0; + rs = SvREFCNT_inc(nrs); + SvREFCNT_inc(cv); calllist(beginav); - rs = "\n"; - rslen = 1; - rschar = '\n'; - rspara = 0; + if (GvCV(gv) == cv) { /* Detach it. */ + SvREFCNT_dec(cv); + GvCV(gv) = 0; /* Was above calllist, why? IZ */ + } + SvREFCNT_dec(rs); + rs = oldrs; curcop = &compiling; curcop->cop_line = oldline; /* might have recursed to yylex */ LEAVE; } - else if (strEQ(s, "END")) { + else if (strEQ(s, "END") && !error_count) { if (!endav) endav = newAV(); av_unshift(endav, 1); @@ -2826,21 +3098,36 @@ OP *block; if (perldb && curstash != debstash) { SV *sv; SV *tmpstr = sv_newmortal(); + static GV *db_postponed; + CV *cv; + HV *hv; sprintf(buf,"%s:%ld",SvPVX(GvSV(curcop->cop_filegv)), (long)subline); sv = newSVpv(buf,0); sv_catpv(sv,"-"); sprintf(buf,"%ld",(long)curcop->cop_line); sv_catpv(sv,buf); - gv_efullname(tmpstr,gv); + gv_efullname3(tmpstr, gv, Nullch); hv_store(GvHV(DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0); + if (!db_postponed) { + db_postponed = gv_fetchpv("DB::postponed", TRUE, SVt_PVHV); + } + hv = GvHVn(db_postponed); + if (HvFILL(hv) >= 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr)) + && (cv = GvCV(db_postponed))) { + dSP; + PUSHMARK(sp); + XPUSHs(tmpstr); + PUTBACK; + perl_call_sv((SV*)cv, G_DISCARD); + } } op_free(op); copline = NOLINE; LEAVE_SCOPE(floor); if (!op) { GvCV(gv) = 0; /* Will remember in SVOP instead. */ - SvFLAGS(cv) |= SVpcv_ANON; + CvANON_on(cv); } return cv; } @@ -2854,7 +3141,7 @@ I32 (*subaddr)(); char *filename; { CV* cv = newXS(name, (void(*)())subaddr, filename); - CvOLDSTYLE(cv) = TRUE; + CvOLDSTYLE_on(cv); CvXSUBANY(cv).any_i32 = ix; return cv; } @@ -2896,7 +3183,7 @@ char *filename; sv_upgrade((SV *)cv, SVt_PVCV); } GvCV(gv) = cv; - CvGV(cv) = SvREFCNT_inc(gv); + CvGV(cv) = GvREFCNT_inc(gv); GvCVGEN(gv) = 0; CvFILEGV(cv) = gv_fetchfile(filename); CvXSUB(cv) = subaddr; @@ -2919,7 +3206,7 @@ char *filename; } if (!name) { GvCV(gv) = 0; /* Will remember elsewhere instead. */ - SvFLAGS(cv) |= SVpcv_ANON; + CvANON_on(cv); } return cv; } @@ -2933,7 +3220,6 @@ OP *block; register CV *cv; char *name; GV *gv; - AV* av; I32 ix; if (op) @@ -2941,7 +3227,7 @@ OP *block; else name = "STDOUT"; gv = gv_fetchpv(name,TRUE, SVt_PVFM); - SvMULTI_on(gv); + GvMULTI_on(gv); if (cv = GvFORM(gv)) { if (dowarn) { line_t oldline = curcop->cop_line; @@ -2954,7 +3240,7 @@ OP *block; } cv = compcv; GvFORM(gv) = cv; - CvGV(cv) = SvREFCNT_inc(gv); + CvGV(cv) = GvREFCNT_inc(gv); CvFILEGV(cv) = curcop->cop_filegv; for (ix = AvFILL(comppad); ix > 0; ix--) { @@ -2962,11 +3248,6 @@ OP *block; SvPADTMP_on(curpad[ix]); } - CvPADLIST(cv) = av = newAV(); - AvREAL_off(av); - av_store(av, 1, SvREFCNT_inc((SV*)comppad)); - AvFILL(av) = 1; - CvROOT(cv) = newUNOP(OP_LEAVEWRITE, 0, scalarseq(block)); CvSTART(cv) = LINKLIST(CvROOT(cv)); CvROOT(cv)->op_next = 0; @@ -2978,25 +3259,6 @@ OP *block; } OP * -newMETHOD(ref,name) -OP *ref; -OP *name; -{ - LOGOP* mop; - Newz(1101, mop, 1, LOGOP); - mop->op_type = OP_METHOD; - mop->op_ppaddr = ppaddr[OP_METHOD]; - mop->op_first = scalar(ref); - mop->op_flags |= OPf_KIDS; - mop->op_private = 1; - mop->op_other = LINKLIST(name); - mop->op_targ = pad_alloc(OP_METHOD, SVs_PADTMP); - mop->op_next = LINKLIST(ref); - ref->op_next = (OP*)mop; - return scalar((OP*)mop); -} - -OP * newANONLIST(op) OP* op; { @@ -3013,12 +3275,13 @@ OP* op; } OP * -newANONSUB(floor, block) +newANONSUB(floor, proto, block) I32 floor; +OP *proto; OP *block; { return newUNOP(OP_REFGEN, 0, - newSVOP(OP_ANONCODE, 0, (SV*)newSUB(floor, 0, block))); + newSVOP(OP_ANONCODE, 0, (SV*)newSUB(floor, 0, proto, block))); } OP * @@ -3113,10 +3376,11 @@ OP *o; } OP * -newCVREF(o) +newCVREF(flags, o) +I32 flags; OP *o; { - return newUNOP(OP_RV2CV, 0, scalar(o)); + return newUNOP(OP_RV2CV, flags, scalar(o)); } OP * @@ -3134,6 +3398,35 @@ OP *o; /* Check routines. */ OP * +ck_anoncode(op) +OP *op; +{ + PADOFFSET ix; + SV* name; + + name = NEWSV(1106,0); + sv_upgrade(name, SVt_PVNV); + sv_setpvn(name, "&", 1); + SvIVX(name) = -1; + SvNVX(name) = 1; + ix = pad_alloc(op->op_type, SVs_PADMY); + av_store(comppad_name, ix, name); + av_store(comppad, ix, cSVOP->op_sv); + SvPADMY_on(cSVOP->op_sv); + cSVOP->op_sv = Nullsv; + cSVOP->op_targ = ix; + return op; +} + +OP * +ck_bitop(op) +OP *op; +{ + op->op_private = hints; + return op; +} + +OP * ck_concat(op) OP *op; { @@ -3172,10 +3465,14 @@ ck_delete(op) OP *op; { op = ck_fun(op); + op->op_private = 0; if (op->op_flags & OPf_KIDS) { OP *kid = cUNOP->op_first; - if (kid->op_type != OP_HELEM) - croak("%s argument is not a HASH element", op_name[op->op_type]); + if (kid->op_type == OP_HSLICE) + op->op_private |= OPpSLICE; + else if (kid->op_type != OP_HELEM) + croak("%s argument is not a HASH element or slice", + op_desc[op->op_type]); null(kid); } return op; @@ -3257,6 +3554,20 @@ OP *op; } OP * +ck_exists(op) +OP *op; +{ + op = ck_fun(op); + if (op->op_flags & OPf_KIDS) { + OP *kid = cUNOP->op_first; + if (kid->op_type != OP_HELEM) + croak("%s argument is not a HASH element", op_desc[op->op_type]); + null(kid); + } + return op; +} + +OP * ck_gvconst(o) register OP *o; { @@ -3272,7 +3583,7 @@ register OP *op; { SVOP *kid = (SVOP*)cUNOP->op_first; - op->op_private = (hints & HINT_STRICT_REFS); + op->op_private |= (hints & HINT_STRICT_REFS); if (kid->op_type == OP_CONST) { int iscv = (op->op_type==OP_RV2CV)*2; GV *gv = 0; @@ -3305,13 +3616,6 @@ register OP *op; } OP * -ck_formline(op) -OP *op; -{ - return ck_fun(op); -} - -OP * ck_ftst(op) OP *op; { @@ -3394,14 +3698,14 @@ OP *op; gv_fetchpv(name, TRUE, SVt_PVAV) )); if (dowarn) warn("Array @%s missing the @ in argument %d of %s()", - name, numargs, op_name[type]); + name, numargs, op_desc[type]); op_free(kid); kid = newop; kid->op_sibling = sibl; *tokid = kid; } else if (kid->op_type != OP_RV2AV && kid->op_type != OP_PADAV) - bad_type(numargs, "array", op, kid); + bad_type(numargs, "array", op_desc[op->op_type], kid); mod(kid, type); break; case OA_HVREF: @@ -3412,14 +3716,14 @@ OP *op; gv_fetchpv(name, TRUE, SVt_PVHV) )); if (dowarn) warn("Hash %%%s missing the %% in argument %d of %s()", - name, numargs, op_name[type]); + name, numargs, op_desc[type]); op_free(kid); kid = newop; kid->op_sibling = sibl; *tokid = kid; } else if (kid->op_type != OP_RV2HV && kid->op_type != OP_PADHV) - bad_type(numargs, "hash", op, kid); + bad_type(numargs, "hash", op_desc[op->op_type], kid); mod(kid, type); break; case OA_CVREF: @@ -3460,9 +3764,9 @@ OP *op; tokid = &kid->op_sibling; kid = kid->op_sibling; } - op->op_private = numargs; + op->op_private |= numargs; if (kid) - return too_many_arguments(op); + return too_many_arguments(op,op_desc[op->op_type]); listkids(op); } else if (opargs[type] & OA_DEFGV) { @@ -3474,7 +3778,7 @@ OP *op; while (oa & OA_OPTIONAL) oa >>= 4; if (oa && oa != OA_LIST) - return too_few_arguments(op); + return too_few_arguments(op,op_desc[op->op_type]); } return op; } @@ -3483,7 +3787,18 @@ OP * ck_glob(op) OP *op; { - GV *gv = newGVgen("main"); + GV *gv = gv_fetchpv("glob", FALSE, SVt_PVCV); + + if (gv && GvIMPORTED_CV(gv)) { + op->op_type = OP_LIST; + op->op_ppaddr = ppaddr[OP_LIST]; + op = newUNOP(OP_ENTERSUB, OPf_STACKED, + append_elem(OP_LIST, op, + scalar(newUNOP(OP_RV2CV, 0, + newGVOP(OP_GV, 0, gv))))); + return ck_subr(op); + } + gv = newGVgen("main"); gv_IOadd(gv); append_elem(OP_GLOB, op, newGVOP(OP_GV, 0, gv)); scalarkids(op); @@ -3504,6 +3819,7 @@ OP *op; if (op->op_flags & OPf_STACKED) { OP* k; op = ck_sort(op); + kid = cLISTOP->op_first->op_sibling; for (k = cLISTOP->op_first->op_sibling->op_next; k; k = k->op_next) { kid = k; } @@ -3534,7 +3850,7 @@ OP *op; kid = cLISTOP->op_first->op_sibling; if (!kid || !kid->op_sibling) - return too_few_arguments(op); + return too_few_arguments(op,op_desc[op->op_type]); for (kid = kid->op_sibling; kid; kid = kid->op_sibling) mod(kid, OP_GREPSTART); @@ -3548,7 +3864,7 @@ OP *op; if (op->op_flags & OPf_KIDS) { OP *kid = cLISTOP->op_first->op_sibling; /* get past pushmark */ if (kid && kid->op_type == OP_CONST) - fbm_compile(((SVOP*)kid)->op_sv, 0); + fbm_compile(((SVOP*)kid)->op_sv); } return ck_fun(op); } @@ -3603,7 +3919,43 @@ OP *op; if (!kid) append_elem(op->op_type, op, newSVREF(newGVOP(OP_GV, 0, defgv)) ); - return listkids(op); + op = listkids(op); + + op->op_private = 0; +#ifdef USE_LOCALE + if (hints & HINT_LOCALE) + op->op_private |= OPpLOCALE; +#endif + + return op; +} + +OP * +ck_fun_locale(op) +OP *op; +{ + op = ck_fun(op); + + op->op_private = 0; +#ifdef USE_LOCALE + if (hints & HINT_LOCALE) + op->op_private |= OPpLOCALE; +#endif + + return op; +} + +OP * +ck_scmp(op) +OP *op; +{ + op->op_private = 0; +#ifdef USE_LOCALE + if (hints & HINT_LOCALE) + op->op_private |= OPpLOCALE; +#endif + + return op; } OP * @@ -3611,6 +3963,7 @@ ck_match(op) OP *op; { cPMOP->op_pmflags |= PMf_RUNTIME; + cPMOP->op_pmpermflags |= PMf_RUNTIME; return op; } @@ -3626,7 +3979,7 @@ ck_repeat(op) OP *op; { if (cBINOP->op_first->op_flags & OPf_PARENS) { - op->op_private = OPpREPEAT_DOLIST; + op->op_private |= OPpREPEAT_DOLIST; cBINOP->op_first = force_list(cBINOP->op_first); } else @@ -3669,8 +4022,9 @@ OP * ck_select(op) OP *op; { + OP* kid; if (op->op_flags & OPf_KIDS) { - OP *kid = cLISTOP->op_first->op_sibling; /* get past pushmark */ + kid = cLISTOP->op_first->op_sibling; /* get past pushmark */ if (kid && kid->op_sibling) { op->op_type = OP_SSELECT; op->op_ppaddr = ppaddr[OP_SSELECT]; @@ -3678,7 +4032,11 @@ OP *op; return fold_constants(op); } } - return ck_fun(op); + op = ck_fun(op); + kid = cLISTOP->op_first->op_sibling; /* get past pushmark */ + if (kid && kid->op_type == OP_RV2GV) + kid->op_private &= ~HINT_STRICT_REFS; + return op; } OP * @@ -3691,8 +4049,9 @@ OP *op; op_free(op); return newUNOP(type, 0, scalar(newUNOP(OP_RV2AV, 0, - scalar(newGVOP(OP_GV, 0, - gv_fetchpv((subline ? "_" : "ARGV"), TRUE, SVt_PVAV) ))))); + scalar(newGVOP(OP_GV, 0, subline + ? defgv + : gv_fetchpv("ARGV", TRUE, SVt_PVAV) ))))); } return scalar(modkids(ck_fun(op), type)); } @@ -3701,6 +4060,12 @@ OP * ck_sort(op) OP *op; { + op->op_private = 0; +#ifdef USE_LOCALE + if (hints & HINT_LOCALE) + op->op_private |= OPpLOCALE; +#endif + if (op->op_flags & OPf_STACKED) { OP *kid = cLISTOP->op_first->op_sibling; /* get past pushmark */ OP *k; @@ -3737,6 +4102,7 @@ OP *op; op->op_flags |= OPf_SPECIAL; } } + return op; } @@ -3793,7 +4159,7 @@ OP *op; scalar(kid); if (kid->op_sibling) - return too_many_arguments(op); + return too_many_arguments(op,op_desc[op->op_type]); return op; } @@ -3802,16 +4168,120 @@ OP * ck_subr(op) OP *op; { - OP *o = ((cUNOP->op_first->op_sibling) - ? cUNOP : ((UNOP*)cUNOP->op_first))->op_first->op_sibling; - - if (o->op_type == OP_RV2CV) - null(o); /* disable rv2cv */ - op->op_private = (hints & HINT_STRICT_REFS); + OP *prev = ((cUNOP->op_first->op_sibling) + ? cUNOP : ((UNOP*)cUNOP->op_first))->op_first; + OP *o = prev->op_sibling; + OP *cvop; + char *proto = 0; + CV *cv = 0; + int optional = 0; + I32 arg = 0; + + for (cvop = o; cvop->op_sibling; cvop = cvop->op_sibling) ; + if (cvop->op_type == OP_RV2CV) { + SVOP* tmpop; + op->op_private |= (cvop->op_private & OPpENTERSUB_AMPER); + null(cvop); /* disable rv2cv */ + tmpop = (SVOP*)((UNOP*)cvop)->op_first; + if (tmpop->op_type == OP_GV) { + cv = GvCV(tmpop->op_sv); + if (cv && SvPOK(cv) && !(op->op_private & OPpENTERSUB_AMPER)) + proto = SvPV((SV*)cv,na); + } + } + op->op_private |= (hints & HINT_STRICT_REFS); if (perldb && curstash != debstash) - op->op_private |= OPpDEREF_DB; - while (o = o->op_sibling) + op->op_private |= OPpENTERSUB_DB; + while (o != cvop) { + if (proto) { + switch (*proto) { + case '\0': + return too_many_arguments(op, CvNAME(cv)); + case ';': + optional = 1; + proto++; + continue; + case '$': + proto++; + arg++; + scalar(o); + break; + case '%': + case '@': + list(o); + arg++; + break; + case '&': + proto++; + arg++; + if (o->op_type != OP_REFGEN && o->op_type != OP_UNDEF) + bad_type(arg, "block", CvNAME(cv), o); + break; + case '*': + proto++; + arg++; + if (o->op_type == OP_RV2GV) + goto wrapref; + { + OP* kid = o; + o = newUNOP(OP_RV2GV, 0, kid); + o->op_sibling = kid->op_sibling; + kid->op_sibling = 0; + prev->op_sibling = o; + } + goto wrapref; + case '\\': + proto++; + arg++; + switch (*proto++) { + case '*': + if (o->op_type != OP_RV2GV) + bad_type(arg, "symbol", CvNAME(cv), o); + goto wrapref; + case '&': + if (o->op_type != OP_RV2CV) + bad_type(arg, "sub", CvNAME(cv), o); + goto wrapref; + case '$': + if (o->op_type != OP_RV2SV && o->op_type != OP_PADSV) + bad_type(arg, "scalar", CvNAME(cv), o); + goto wrapref; + case '@': + if (o->op_type != OP_RV2AV && o->op_type != OP_PADAV) + bad_type(arg, "array", CvNAME(cv), o); + goto wrapref; + case '%': + if (o->op_type != OP_RV2HV && o->op_type != OP_PADHV) + bad_type(arg, "hash", CvNAME(cv), o); + wrapref: + { + OP* kid = o; + o = newUNOP(OP_REFGEN, 0, kid); + o->op_sibling = kid->op_sibling; + kid->op_sibling = 0; + prev->op_sibling = o; + } + break; + default: goto oops; + } + break; + case ' ': + proto++; + continue; + default: + oops: + croak("Malformed prototype for %s: %s", + CvNAME(cv),SvPV((SV*)cv,na)); + } + } + else + list(o); mod(o, OP_ENTERSUB); + prev = o; + o = o->op_sibling; + } + if (proto && !optional && *proto == '$') + return too_few_arguments(op, CvNAME(cv)); return op; } @@ -3854,12 +4324,14 @@ register OP* o; for (; o; o = o->op_next) { if (o->op_seq) break; + if (!op_seqmax) + op_seqmax++; op = o; switch (o->op_type) { case OP_NEXTSTATE: case OP_DBSTATE: curcop = ((COP*)o); /* for warnings */ - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; case OP_CONCAT: @@ -3872,11 +4344,11 @@ register OP* o; case OP_QUOTEMETA: if (o->op_next->op_type == OP_STRINGIFY) null(o->op_next); - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; case OP_STUB: if ((o->op_flags & (OPf_KNOW|OPf_LIST)) != (OPf_KNOW|OPf_LIST)) { - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; /* Scalar stub must produce undef. List stub is noop */ } goto nothin; @@ -3892,12 +4364,12 @@ register OP* o; oldop->op_next = o->op_next; continue; } - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; case OP_GV: if (o->op_next->op_type == OP_RV2SV) { - if (!(o->op_next->op_private & (OPpDEREF_HV|OPpDEREF_AV))) { + if (!(o->op_next->op_private & OPpDEREF)) { null(o->op_next); o->op_private |= o->op_next->op_private & OPpLVAL_INTRO; o->op_next = o->op_next->op_next; @@ -3911,8 +4383,7 @@ register OP* o; if (pop->op_type == OP_CONST && (op = pop->op_next) && pop->op_next->op_type == OP_AELEM && - !(pop->op_next->op_private & - (OPpDEREF_HV|OPpDEREF_AV|OPpLVAL_INTRO)) && + !(pop->op_next->op_private & (OPpDEREF|OPpLVAL_INTRO)) && (i = SvIV(((SVOP*)pop)->op_sv) - compiling.cop_arybase) <= 255 && i >= 0) @@ -3929,25 +4400,25 @@ register OP* o; GvAVn((GV*)(((SVOP*)o)->op_sv)); } } - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; case OP_MAPWHILE: case OP_GREPWHILE: case OP_AND: case OP_OR: - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; peep(cLOGOP->op_other); break; case OP_COND_EXPR: - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; peep(cCONDOP->op_true); peep(cCONDOP->op_false); break; case OP_ENTERLOOP: - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; peep(cLOOP->op_redoop); peep(cLOOP->op_nextop); peep(cLOOP->op_lastop); @@ -3955,12 +4426,12 @@ register OP* o; case OP_MATCH: case OP_SUBST: - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; peep(cPMOP->op_pmreplstart); break; case OP_EXEC: - o->op_seq = ++op_seqmax; + 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_DIE) { @@ -3974,7 +4445,7 @@ register OP* o; } break; default: - o->op_seq = ++op_seqmax; + o->op_seq = op_seqmax++; break; } oldop = o;