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*
CV* cv;
{
SV* tmpsv = sv_newmortal();
- gv_efullname(tmpsv, CvGV(cv));
+ gv_efullname3(tmpsv, CvGV(cv), Nullch);
return SvPV(tmpsv,na);
}
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) {
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, I32 seq, CV* startcv, I32 cx_ix)
+pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)
#endif
{
CV *cv;
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);
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));
- CvCLONE_on(compcv);
return newoff;
}
}
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 = 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;
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(Perl_debug_log, "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;
}
{
if (!po)
croak("panic: pad_sv po");
- DEBUG_X(fprintf(Perl_debug_log, "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 */
}
croak("panic: pad_free curpad");
if (!po)
croak("panic: pad_free po");
- DEBUG_X(fprintf(Perl_debug_log, "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)
croak("panic: pad_swipe curpad");
if (!po)
croak("panic: pad_swipe po");
- DEBUG_X(fprintf(Perl_debug_log, "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]);
if (AvARRAY(comppad) != curpad)
croak("panic: pad_reset curpad");
- DEBUG_X(fprintf(Perl_debug_log, "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)
break;
case OP_NEXTSTATE:
case OP_DBSTATE:
+ Safefree(cCOP->cop_label);
SvREFCNT_dec(cCOP->cop_filegv);
break;
- /* case OP_ANONCODE: XXX breaks eval of anon subs in closures (cf. Opcode) */
case OP_CONST:
SvREFCNT_dec(cSVOP->op_sv);
break;
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;
default:
if (!(opargs[op->op_type] & OA_FOLDCONST))
break;
+ /* FALL THROUGH */
+ case OP_REPEAT:
if (op->op_flags & OPf_STACKED)
break;
/* FALL THROUGH */
op->op_ppaddr = ppaddr[OP_PREDEC];
break;
- case OP_REPEAT:
- scalarvoid(cBINOP->op_first);
- useless = op_desc[op->op_type];
- break;
-
case OP_OR:
case OP_AND:
case OP_COND_EXPR:
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);
{
OP *kid;
SV *sv;
- char mtype;
if (!op || error_count)
return op;
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)) {
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++;
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->op_sibling, type);
break;
ref(cUNOP->op_first, op->op_type);
/* FALL THROUGH */
case OP_PADSV:
- 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;
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;
}
int
-block_start()
+block_start(full)
+int full;
{
int retval = savestack_ix;
- SAVEINT(comppad_name_floor);
- if ((comppad_name_fill = AvFILL(comppad_name)) > 0)
- comppad_name_floor = comppad_name_fill;
- else
- comppad_name_floor = 0;
- 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;
}
pmop->op_flags = flags;
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) {
pmop->op_pmnext = HvPMROOT(curstash);
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)) {
- 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;
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)
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;
else {
sv = newGVOP(OP_GV, 0, defgv);
}
- if (expr->op_type == OP_RV2AV) {
+ if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
expr = scalar(ref(expr, OP_ITER));
iterflags |= OPf_STACKED;
}
}
}
-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);
cv = compcv = (CV*)NEWSV(1104,0);
sv_upgrade((SV *)cv, SVt_PVCV);
CvCLONED_on(cv);
+ if (CvANON(proto))
+ CvANON_on(cv);
CvFILEGV(cv) = CvFILEGV(proto);
CvGV(cv) = GvREFCNT_inc(CvGV(proto));
CvSTASH(cv) = CvSTASH(proto);
CvROOT(cv) = CvROOT(proto);
CvSTART(cv) = CvSTART(proto);
- if (CvOUTSIDE(proto))
- CvOUTSIDE(cv) = (CV*)SvREFCNT_inc((SV*)CvOUTSIDE(proto));
+ if (outside)
+ CvOUTSIDE(cv) = (CV*)SvREFCNT_inc(outside);
comppad = newAV();
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 @_ */
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 *
+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;
if (GvCVGEN(gv))
cv = 0; /* just a cached method */
else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
- if (dowarn && strNE(name, "BEGIN")) {/* already defined (or promised)? */
+ 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);
if (proto) {
char *p = SvPVx(((SVOP*)proto)->op_sv, na);
- if (SvPOK(cv) && strNE(SvPV((SV*)cv,na), p))
- warn("Prototype mismatch: (%s) vs (%s)", SvPV((SV*)cv, na), p);
sv_setpv((SV*)cv, p);
op_free(proto);
}
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;
/* 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;
{
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_desc[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;
}
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;
{
}
OP *
-ck_formline(op)
-OP *op;
-{
- return ck_fun(op);
-}
-
-OP *
ck_ftst(op)
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);
}
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 *
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;
op->op_flags |= OPf_SPECIAL;
}
}
+
return op;
}
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;
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)