/* op.c
*
- * Copyright (c) 1991-1994, Larry Wall
+ * Copyright (c) 1991-1997, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
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 bool scalar_mod_type _((OP *op, I32 type));
static OP *scalarboolean _((OP *op));
static OP *too_few_arguments _((OP *op, char* name));
static OP *too_many_arguments _((OP *op, char* name));
int saweval;
for (cv = startcv; cv; cv = CvOUTSIDE(cv)) {
- AV* curlist = CvPADLIST(cv);
- SV** svp = av_fetch(curlist, 0, FALSE);
+ AV *curlist = CvPADLIST(cv);
+ SV **svp = av_fetch(curlist, 0, FALSE);
AV *curname;
+
if (!svp || *svp == &sv_undef)
continue;
curname = (AV*)*svp;
depth = CvDEPTH(cv);
if (!depth) {
- if (newoff && !CvUNIQUE(cv))
- return 0; /* don't clone inactive sub's stack frame */
+ if (newoff) {
+ if (SvFAKE(sv))
+ continue;
+ return 0; /* don't clone from inactive 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);
+ SV *namesv = NEWSV(1103,0);
newoff = pad_alloc(OP_PADSV, SVs_PADMY);
- sv_upgrade(sv, SVt_PVNV);
- sv_setpv(sv, name);
- av_store(comppad_name, newoff, sv);
- SvNVX(sv) = (double)curcop->cop_seq;
- SvIVX(sv) = 999999999; /* A ref, intro immediately */
- SvFLAGS(sv) |= SVf_FAKE;
- if (CvANON(compcv)) {
+ sv_upgrade(namesv, SVt_PVNV);
+ sv_setpv(namesv, name);
+ av_store(comppad_name, newoff, namesv);
+ SvNVX(namesv) = (double)curcop->cop_seq;
+ SvIVX(namesv) = 999999999; /* A ref, intro immediately */
+ SvFAKE_on(namesv); /* A ref, not a real var */
+ if (CvANON(compcv) || SvTYPE(compcv) == SVt_PVFM) {
/* "It's closures all the way down." */
CvCLONE_on(compcv);
- if (cv != startcv) {
+ if (cv == startcv) {
+ if (CvANON(compcv))
+ oldsv = Nullsv; /* no need to keep ref */
+ }
+ else {
CV *bcv;
for (bcv = startcv;
bcv && bcv != cv && !CvCLONE(bcv);
if (CvANON(bcv))
CvCLONE_on(bcv);
else {
- if (dowarn)
- warn("Value of %s may be unavailable",
+ if (dowarn && !CvUNIQUE(cv))
+ warn(
+ "Variable \"%s\" may be unavailable",
name);
break;
}
}
}
}
- else {
- if (dowarn && !CvUNIQUE(cv))
- warn("Value of %s will not stay shared", name);
+ else if (!CvUNIQUE(compcv)) {
+ if (dowarn && !SvFAKE(sv) && !CvUNIQUE(cv))
+ warn("Variable \"%s\" will not stay shared", name);
}
}
av_store(comppad, newoff, SvREFCNT_inc(oldsv));
}
break;
case CXt_EVAL:
- 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;
+ switch (cx->blk_eval.old_op_type) {
+ case OP_ENTEREVAL:
+ saweval = i;
+ break;
+ case OP_REQUIRE:
+ /* require must have its own scope */
+ return 0;
+ }
break;
case CXt_SUB:
if (!saweval)
char *name;
{
I32 off;
+ I32 pendoff = 0;
SV *sv;
SV **svp = AvARRAY(comppad_name);
U32 seq = cop_seqmax;
for (off = AvFILL(comppad_name); off > 0; off--) {
if ((sv = svp[off]) &&
sv != &sv_undef &&
- seq <= SvIVX(sv) &&
- seq > I_32(SvNVX(sv)) &&
+ (!SvIVX(sv) ||
+ (seq <= SvIVX(sv) &&
+ seq > I_32(SvNVX(sv)))) &&
strEQ(SvPVX(sv), name))
{
- return (PADOFFSET)off;
+ if (SvIVX(sv))
+ return (PADOFFSET)off;
+ pendoff = off; /* this pending def. will override import */
}
}
/* See if it's in a nested scope */
off = pad_findlex(name, 0, seq, CvOUTSIDE(compcv), cxstack_ix);
- if (off)
+ if (off) {
+ /* If there is a pending local definition, this new alias must die */
+ if (pendoff)
+ SvIVX(AvARRAY(comppad_name)[off]) = seq;
return off;
+ }
return 0;
}
{
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 sv %lu\n", (unsigned long)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(PerlIO_printf(Perl_debug_log, "Pad free %d\n", po));
- if (curpad[po] && curpad[po] != &sv_undef)
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad free %lu\n", (unsigned long)po));
+ if (curpad[po] && !SvIMMORTAL(curpad[po]))
SvPADTMP_off(curpad[po]);
if ((I32)po < padix)
padix = po - 1;
croak("panic: pad_swipe curpad");
if (!po)
croak("panic: pad_swipe po");
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %d\n", po));
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %lu\n", (unsigned long)po));
SvPADTMP_off(curpad[po]);
curpad[po] = NEWSV(1107,0);
SvPADTMP_on(curpad[po]);
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)
+ if (curpad[po] && !SvIMMORTAL(curpad[po]))
SvPADTMP_off(curpad[po]);
}
padix = padix_floor;
OP *kid;
/* assumes no premature commitment */
- if (!op || (op->op_flags & OPf_KNOW) || op->op_type == OP_RETURN
- || error_count)
+ if (!op || (op->op_flags & OPf_WANT) || error_count
+ || op->op_type == OP_RETURN)
return op;
- op->op_flags &= ~OPf_LIST;
- op->op_flags |= OPf_KNOW;
+ op->op_flags = (op->op_flags & ~OPf_WANT) | OPf_WANT_SCALAR;
switch (op->op_type) {
case OP_REPEAT:
break;
case OP_LEAVE:
case OP_LEAVETRY:
- scalar(cLISTOP->op_first);
- /* FALL THROUGH */
+ kid = cLISTOP->op_first;
+ scalar(kid);
+ while (kid = kid->op_sibling) {
+ if (kid->op_sibling)
+ scalarvoid(kid);
+ else
+ scalar(kid);
+ }
+ curcop = &compiling;
+ break;
case OP_SCOPE:
case OP_LINESEQ:
case OP_LIST:
char* useless = 0;
SV* sv;
- if (!op || error_count)
- return op;
- if (op->op_flags & OPf_LIST)
+ /* assumes no premature commitment */
+ if (!op || (op->op_flags & OPf_WANT) == OPf_WANT_LIST || error_count
+ || op->op_type == OP_RETURN)
return op;
- op->op_flags |= OPf_KNOW;
+ op->op_flags = (op->op_flags & ~OPf_WANT) | OPf_WANT_VOID;
switch (op->op_type) {
default:
case OP_AELEM:
case OP_AELEMFAST:
case OP_ASLICE:
- case OP_VALUES:
- case OP_KEYS:
case OP_HELEM:
case OP_HSLICE:
case OP_UNPACK:
for (kid = cUNOP->op_first->op_sibling; kid; kid = kid->op_sibling)
scalarvoid(kid);
break;
+
case OP_NULL:
if (op->op_targ == OP_NEXTSTATE || op->op_targ == OP_DBSTATE)
curcop = ((COP*)op); /* for warning below */
if (op->op_flags & OPf_STACKED)
break;
+ /* FALL THROUGH */
case OP_ENTERTRY:
case OP_ENTER:
case OP_SCALAR:
if (!(op->op_flags & OPf_KIDS))
break;
+ /* FALL THROUGH */
case OP_SCOPE:
case OP_LEAVE:
case OP_LEAVETRY:
case OP_LEAVELOOP:
- op->op_private |= OPpLEAVE_VOID;
case OP_LINESEQ:
case OP_LIST:
for (kid = cLISTOP->op_first; kid; kid = kid->op_sibling)
scalarvoid(kid);
break;
+ case OP_REQUIRE:
+ /* since all requires must return a value, they're never void */
+ op->op_flags &= ~OPf_WANT;
+ return scalar(op);
case OP_SPLIT:
if ((kid = ((LISTOP*)op)->op_first) && kid->op_type == OP_PUSHRE) {
if (!kPMOP->op_pmreplroot)
deprecate("implicit split to @_");
}
break;
- case OP_DELETE:
- op->op_private |= OPpLEAVE_VOID;
- break;
}
if (useless && dowarn)
warn("Useless use of %s in void context", useless);
OP *kid;
/* assumes no premature commitment */
- if (!op || (op->op_flags & OPf_KNOW) || op->op_type == OP_RETURN
- || error_count)
+ if (!op || (op->op_flags & OPf_WANT) || error_count
+ || op->op_type == OP_RETURN)
return op;
- op->op_flags |= (OPf_KNOW | OPf_LIST);
+ op->op_flags = (op->op_flags & ~OPf_WANT) | OPf_WANT_LIST;
switch (op->op_type) {
case OP_FLOP:
break;
case OP_LEAVE:
case OP_LEAVETRY:
- list(cLISTOP->op_first);
- /* FALL THROUGH */
+ kid = cLISTOP->op_first;
+ list(kid);
+ while (kid = kid->op_sibling) {
+ if (kid->op_sibling)
+ scalarvoid(kid);
+ else
+ list(kid);
+ }
+ curcop = &compiling;
+ break;
case OP_SCOPE:
case OP_LINESEQ:
for (kid = cLISTOP->op_first; kid; kid = kid->op_sibling) {
return op;
switch (op->op_type) {
+ case OP_UNDEF:
+ return op;
case OP_CONST:
if (!(op->op_private & (OPpCONST_ARYBASE)))
goto nomod;
}
/* FALL THROUGH */
case OP_RV2GV:
+ if (scalar_mod_type(op, type))
+ goto nomod;
ref(cUNOP->op_first, op->op_type);
/* FALL THROUGH */
case OP_AASSIGN:
croak("Can't localize a reference");
ref(cUNOP->op_first, op->op_type);
/* FALL THROUGH */
- case OP_UNDEF:
case OP_GV:
case OP_AV2ARYLEN:
case OP_SASSIGN:
modcount = 10000;
if (type == OP_REFGEN && op->op_flags & OPf_PARENS)
return op; /* Treat \(@foo) like ordinary list. */
+ if (scalar_mod_type(op, type))
+ goto nomod;
/* FALL THROUGH */
case OP_PADSV:
modcount++;
case OP_AELEM:
case OP_HELEM:
ref(cBINOP->op_first, op->op_type);
+ if (type == OP_ENTERSUB &&
+ !(op->op_private & (OPpLVAL_INTRO | OPpDEREF)))
+ op->op_private |= OPpLVAL_DEFER;
modcount++;
break;
return op;
}
+static bool
+scalar_mod_type(op, type)
+OP *op;
+I32 type;
+{
+ switch (type) {
+ case OP_SASSIGN:
+ if (op->op_type == OP_RV2GV)
+ return FALSE;
+ /* FALL THROUGH */
+ case OP_PREINC:
+ case OP_PREDEC:
+ case OP_POSTINC:
+ case OP_POSTDEC:
+ case OP_I_PREINC:
+ case OP_I_PREDEC:
+ case OP_I_POSTINC:
+ case OP_I_POSTDEC:
+ case OP_POW:
+ case OP_MULTIPLY:
+ case OP_DIVIDE:
+ case OP_MODULO:
+ case OP_REPEAT:
+ case OP_ADD:
+ case OP_SUBTRACT:
+ case OP_I_MULTIPLY:
+ case OP_I_DIVIDE:
+ case OP_I_MODULO:
+ case OP_I_ADD:
+ case OP_I_SUBTRACT:
+ case OP_LEFT_SHIFT:
+ case OP_RIGHT_SHIFT:
+ case OP_BIT_AND:
+ case OP_BIT_XOR:
+ case OP_BIT_OR:
+ case OP_CONCAT:
+ case OP_SUBST:
+ case OP_TRANS:
+ case OP_ANDASSIGN: /* may work later */
+ case OP_ORASSIGN: /* may work later */
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
OP *
refkids(op, type)
OP *op;
{
OP *op;
+ if (dowarn &&
+ (left->op_type == OP_RV2AV ||
+ left->op_type == OP_RV2HV ||
+ left->op_type == OP_PADAV ||
+ left->op_type == OP_PADHV)) {
+ char *desc = op_desc[(right->op_type == OP_SUBST ||
+ right->op_type == OP_TRANS)
+ ? right->op_type : OP_MATCH];
+ char *sample = ((left->op_type == OP_RV2AV ||
+ left->op_type == OP_PADAV)
+ ? "@array" : "%hash");
+ warn("Applying %s to %s will act on scalar(%s)", desc, sample, sample);
+ }
+
if (right->op_type == OP_MATCH ||
right->op_type == OP_SUBST ||
right->op_type == OP_TRANS) {
peep(eval_start);
}
else {
- if (!op) {
- main_start = 0;
+ if (!op)
return;
- }
main_root = scope(sawparens(scalarvoid(op)));
curcop = &compiling;
main_start = LINKLIST(main_root);
main_root->op_next = 0;
peep(main_start);
- main_cv = compcv;
compcv = 0;
+
+ /* Register with debugger */
+ if (perldb) {
+ CV *cv = perl_get_cv("DB::postponed", FALSE);
+ if (cv) {
+ dSP;
+ PUSHMARK(sp);
+ XPUSHs((SV*)compiling.cop_filegv);
+ PUTBACK;
+ perl_call_sv((SV*)cv, G_DISCARD);
+ }
+ }
}
}
if (!op || op->op_type != OP_LIST)
op = newLISTOP(OP_LIST, 0, op, Nullop);
else
- op->op_flags &= ~(OPf_KNOW|OPf_LIST);
+ op->op_flags &= ~OPf_WANT;
if (!(opargs[type] & OA_MARK))
null(cLISTOP->op_first);
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);
+ right->op_flags &= ~OPf_WANT;
/* "I don't know and I don't care." */
return right;
}
}
cop->op_flags = flags;
cop->op_private = 0 | (flags >> 8);
+#ifdef NATIVE_HINTS
+ cop->op_private |= NATIVE_HINTS;
+#endif
cop->op_next = (OP*)cop;
if (label) {
cop->cop_line = copline;
copline = NOLINE;
}
- cop->cop_filegv = GvREFCNT_inc(curcop->cop_filegv);
+ cop->cop_filegv = (GV*)SvREFCNT_inc(curcop->cop_filegv);
cop->cop_stash = curstash;
if (perldb && curstash != debstash) {
break;
case OP_SASSIGN:
- if (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB)
+ if (k1->op_type == OP_READDIR
+ || k1->op_type == OP_GLOB
+ || k1->op_type == OP_EACH)
warnop = k1->op_type;
break;
}
if (warnop) {
line_t oldline = curcop->cop_line;
curcop->cop_line = copline;
- warn("Value of %s construct can be \"0\"; test with defined()",
- op_desc[warnop]);
- curcop->cop_line = oldline;
+ warn("Value of %s%s can be \"0\"; test with defined()",
+ op_desc[warnop],
+ ((warnop == OP_READLINE || warnop == OP_GLOB)
+ ? " construct" : "() operator"));
+ curcop->cop_line = oldline;
}
}
if (expr) {
if (once && expr->op_type == OP_CONST && !SvTRUE(((SVOP*)expr)->op_sv))
return block; /* do {} while 0 does once */
- else if (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB)
- expr = newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr);
+ if (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB) {
+ expr = newUNOP(OP_DEFINED, 0,
+ newASSIGNOP(0, newSVREF(newGVOP(OP_GV, 0, defgv)), 0, expr) );
+ }
}
listop = append_elem(OP_LINESEQ, block, newOP(OP_UNSTACK, 0));
CvROOT(cv) = Nullop;
LEAVE;
}
+ CvFLAGS(cv) = 0;
SvREFCNT_dec(CvGV(cv));
CvGV(cv) = Nullgv;
SvREFCNT_dec(CvOUTSIDE(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);
+ AV* pad_name;
+ AV* pad;
+ SV** pname;
+ SV** ppad;
I32 ix;
PerlIO_printf(Perl_debug_log, "\tCV=0x%p (%s), OUTSIDE=0x%p (%s)\n",
(CvANON(cv) ? "ANON"
: (cv == main_cv) ? "MAIN"
: CvUNIQUE(outside) ? "UNIQUE"
- : CvGV(cv) ? GvNAME(CvGV(cv)) : "?mystery?"),
+ : CvGV(cv) ? GvNAME(CvGV(cv)) : "UNDEFINED"),
outside,
(!outside ? "null"
: CvANON(outside) ? "ANON"
: (outside == main_cv) ? "MAIN"
: CvUNIQUE(outside) ? "UNIQUE"
- : CvGV(outside) ? GvNAME(CvGV(outside)) : "?mystery?"));
+ : CvGV(outside) ? GvNAME(CvGV(outside)) : "UNDEFINED"));
+
+ if (!padlist)
+ return;
- for (ix = 1; ix <= AvFILL(pad); ix++) {
+ pad_name = (AV*)*av_fetch(padlist, 0, FALSE);
+ pad = (AV*)*av_fetch(padlist, 1, FALSE);
+ pname = AvARRAY(pad_name);
+ ppad = AvARRAY(pad);
+
+ for (ix = 1; ix <= AvFILL(pad_name); ix++) {
if (SvPOK(pname[ix]))
- PerlIO_printf(Perl_debug_log, "\t%4d. 0x%p (\"%s\" %ld-%ld)\n",
- ix, ppad[ix], SvPVX(pname[ix]),
+ PerlIO_printf(Perl_debug_log, "\t%4d. 0x%p (%s\"%s\" %ld-%ld)\n",
+ ix, ppad[ix],
+ SvFAKE(pname[ix]) ? "FAKE " : "",
+ SvPVX(pname[ix]),
(long)I_32(SvNVX(pname[ix])),
(long)SvIVX(pname[ix]));
}
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);
AV* comppadlist;
CV* cv;
SAVESPTR(compcv);
cv = compcv = (CV*)NEWSV(1104,0);
- sv_upgrade((SV *)cv, SVt_PVCV);
+ sv_upgrade((SV *)cv, SvTYPE(proto));
CvCLONED_on(cv);
if (CvANON(proto))
CvANON_on(cv);
CvFILEGV(cv) = CvFILEGV(proto);
- CvGV(cv) = GvREFCNT_inc(CvGV(proto));
+ CvGV(cv) = (GV*)SvREFCNT_inc(CvGV(proto));
CvSTASH(cv) = CvSTASH(proto);
CvROOT(cv) = CvROOT(proto);
CvSTART(cv) = CvSTART(proto);
if (outside)
CvOUTSIDE(cv) = (CV*)SvREFCNT_inc(outside);
+ if (SvPOK(proto))
+ sv_setpvn((SV*)cv, SvPVX(proto), SvCUR(proto));
+
comppad = newAV();
comppadlist = newAV();
av_store(comppad, 0, (SV*)av);
AvFLAGS(av) = AVf_REIFY;
- 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]),
+ for (ix = fpad; ix > 0; ix--) {
+ SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
+ if (namesv && namesv != &sv_undef) {
+ char *name = SvPVX(namesv); /* XXX */
+ if (SvFLAGS(namesv) & SVf_FAKE) { /* lexical from outside? */
+ I32 off = pad_findlex(name, ix, SvIVX(namesv),
CvOUTSIDE(cv), cxstack_ix);
if (!off)
curpad[ix] = SvREFCNT_inc(ppad[ix]);
croak("panic: cv_clone: %s", name);
}
else { /* our own lexical */
+ SV* sv;
if (*name == '&') {
/* anon code -- we'll come back for it */
sv = SvREFCNT_inc(ppad[ix]);
}
}
else {
- sv = NEWSV(0,0);
+ SV* 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]) == '&'
+ for (ix = fpad; ix > 0; ix--) {
+ SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
+ if (namesv
+ && namesv != &sv_undef
+ && !(SvFLAGS(namesv) & SVf_FAKE)
+ && *SvPVX(namesv) == '&'
&& CvCLONE(ppad[ix]))
{
CV *kid = cv_clone2((CV*)ppad[ix], cv);
return cv_clone2(proto, CvOUTSIDE(proto));
}
+void
+cv_ckproto(cv, gv, p)
+CV* cv;
+GV* gv;
+char* p;
+{
+ if ((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) {
+ char* buf;
+ SV* name = Nullsv;
+
+ if (gv)
+ gv_efullname3(name = NEWSV(606, 40), gv, Nullch);
+ New(607, buf, ((name ? SvCUR(name) : 0)
+ + (SvPOK(cv) ? SvCUR(cv) : 0)
+ + (p ? strlen(p) : 0)
+ + 60), char);
+ strcpy(buf, "Prototype mismatch:");
+ if (name) {
+ sprintf(buf + strlen(buf), " sub %s", SvPVX(name));
+ SvREFCNT_dec(name);
+ }
+ if (SvPOK(cv))
+ sprintf(buf + strlen(buf), " (%s)", SvPVX(cv));
+ strcat(buf, " vs ");
+ sprintf(buf + strlen(buf), p ? "(%s)" : "none", p);
+ warn("%s", buf);
+ Safefree(buf);
+ }
+}
+
SV *
cv_const_sv(cv)
-CV *cv;
+CV* cv;
{
OP *o;
- SV *sv = Nullsv;
+ SV *sv;
- 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;
+ if (!cv || !SvPOK(cv) || SvCUR(cv))
+ return Nullsv;
+ sv = Nullsv;
+ 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 (sv)
+ return Nullsv;
+ if (type == OP_CONST)
sv = ((SVOP*)o)->op_sv;
+ else if (type == OP_PADSV) {
+ AV* pad = (AV*)(AvARRAY(CvPADLIST(cv))[1]);
+ sv = pad ? AvARRAY(pad)[o->op_targ] : Nullsv;
+ if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1))
+ return Nullsv;
}
+ else
+ return Nullsv;
}
+ if (sv)
+ SvREADONLY_on(sv);
return sv;
}
OP *proto;
OP *block;
{
+ char *name = op ? SvPVx(cSVOP->op_sv, na) : Nullch;
+ GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
+ char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch;
register CV *cv;
- char *name = op ? SvPVx(cSVOP->op_sv, na) : "__ANON__";
- GV* gv = gv_fetchpv(name, GV_ADDMULTI, SVt_PVCV);
- AV* av;
I32 ix;
- if (op) {
+ if (op)
SAVEFREEOP(op);
- sub_generation++;
- }
- if (cv = GvCV(gv)) {
- if (GvCVGEN(gv)) {
- /* just a cached method */
- SvREFCNT_dec(cv);
- cv = 0;
- }
- else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
- /* 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 (proto)
+ SAVEFREEOP(proto);
+
+ if (!name || GvCVGEN(gv))
+ cv = Nullcv;
+ else if (cv = GvCV(gv)) {
+ cv_ckproto(cv, gv, ps);
+ /* already defined (or promised)? */
+ if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
+ SV* const_sv;
+ if (!block) {
+ /* just a "sub foo;" when &foo is already defined */
+ SAVEFREESV(compcv);
+ goto done;
}
- if ((const_sv || dowarn) && strNE(name, "BEGIN")) {
+ const_sv = cv_const_sv(cv);
+ if (const_sv || dowarn) {
line_t oldline = curcop->cop_line;
-
curcop->cop_line = copline;
warn(const_sv ? "Constant subroutine %s redefined"
- : "Subroutine %s redefined",name);
+ : "Subroutine %s redefined", name);
curcop->cop_line = oldline;
}
SvREFCNT_dec(cv);
- cv = 0;
+ cv = Nullcv;
}
}
if (cv) { /* must reuse cv if autoloaded */
cv_undef(cv);
- CvFLAGS(cv) = (CvFLAGS(cv)&~CVf_CLONE) | (CvFLAGS(compcv)&CVf_CLONE);
+ CvFLAGS(cv) = CvFLAGS(compcv);
CvOUTSIDE(cv) = CvOUTSIDE(compcv);
CvOUTSIDE(compcv) = 0;
CvPADLIST(cv) = CvPADLIST(compcv);
}
else {
cv = compcv;
+ if (name) {
+ GvCV(gv) = cv;
+ GvCVGEN(gv) = 0;
+ sub_generation++;
+ }
}
- GvCV(gv) = cv;
- GvCVGEN(gv) = 0;
+ CvGV(cv) = (GV*)SvREFCNT_inc(gv);
CvFILEGV(cv) = curcop->cop_filegv;
- 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 (ps)
+ sv_setpv((SV*)cv, ps);
if (error_count) {
op_free(block);
block = Nullop;
+ if (name) {
+ char *s = strrchr(name, ':');
+ s = s ? s+1 : name;
+ if (strEQ(s, "BEGIN")) {
+ char *not_safe =
+ "BEGIN not safe after errors--compilation aborted";
+ if (in_eval & 4)
+ croak(not_safe);
+ else {
+ /* force display of errors found but not reported */
+ sv_catpv(GvSV(errgv), not_safe);
+ croak("%s", SvPVx(GvSV(errgv), na));
+ }
+ }
+ }
}
if (!block) {
- CvROOT(cv) = 0;
copline = NOLINE;
LEAVE_SCOPE(floor);
return cv;
}
- av = newAV(); /* Will be @_ */
- av_extend(av, 0);
- av_store(comppad, 0, (SV*)av);
- AvFLAGS(av) = AVf_REIFY;
+ if (AvFILL(comppad_name) < AvFILL(comppad))
+ av_store(comppad_name, AvFILL(comppad), Nullsv);
- for (ix = AvFILL(comppad); ix > 0; ix--) {
- if (!SvPADMY(curpad[ix]))
- SvPADTMP_on(curpad[ix]);
+ if (CvCLONE(cv)) {
+ SV **namep = AvARRAY(comppad_name);
+ for (ix = AvFILL(comppad); ix > 0; ix--) {
+ SV *namesv;
+
+ if (SvIMMORTAL(curpad[ix]))
+ continue;
+ /*
+ * The only things that a clonable function needs in its
+ * pad are references to outer lexicals and anonymous subs.
+ * The rest are created anew during cloning.
+ */
+ if (!((namesv = namep[ix]) != Nullsv &&
+ namesv != &sv_undef &&
+ (SvFAKE(namesv) ||
+ *SvPVX(namesv) == '&')))
+ {
+ SvREFCNT_dec(curpad[ix]);
+ curpad[ix] = Nullsv;
+ }
+ }
}
+ else {
+ AV *av = newAV(); /* Will be @_ */
+ av_extend(av, 0);
+ av_store(comppad, 0, (SV*)av);
+ AvFLAGS(av) = AVf_REIFY;
- if (AvFILL(comppad_name) < AvFILL(comppad))
- av_store(comppad_name, AvFILL(comppad), Nullsv);
+ for (ix = AvFILL(comppad); ix > 0; ix--) {
+ if (SvIMMORTAL(curpad[ix]))
+ continue;
+ if (!SvPADMY(curpad[ix]))
+ SvPADTMP_on(curpad[ix]);
+ }
+ }
CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block));
CvSTART(cv) = LINKLIST(CvROOT(cv));
CvROOT(cv)->op_next = 0;
peep(CvSTART(cv));
- if (op) {
- char *s = strrchr(name,':');
- if (s)
+ if (name) {
+ char *s;
+
+ 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_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);
+ XPUSHs(tmpstr);
+ PUTBACK;
+ perl_call_sv((SV*)cv, G_DISCARD);
+ }
+ }
+
+ if ((s = strrchr(name,':')))
s++;
else
s = name;
- if (strEQ(s, "BEGIN") && !error_count) {
+ if (strEQ(s, "BEGIN")) {
+ I32 oldscope = scopestack_ix;
ENTER;
SAVESPTR(compiling.cop_filegv);
SAVEI16(compiling.cop_line);
DEBUG_x( dump_sub(gv) );
av_push(beginav, (SV *)cv);
GvCV(gv) = 0;
- calllist(beginav);
+ call_list(oldscope, beginav);
curcop = &compiling;
LEAVE;
}
}
- 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_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);
- }
- }
-
- if (!op)
- GvCV(gv) = 0; /* Will remember in SVOP instead. */
-
+ done:
copline = NOLINE;
LEAVE_SCOPE(floor);
return cv;
void (*subaddr) _((CV*));
char *filename;
{
+ GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
register CV *cv;
- GV *gv = gv_fetchpv((name ? name : "__ANON__"), GV_ADDMULTI, SVt_PVCV);
-
- if (name)
- sub_generation++;
- if (cv = GvCV(gv)) {
- if (GvCVGEN(gv))
- cv = 0; /* just a cached method */
- else if (CvROOT(cv) || CvXSUB(cv)) { /* already defined? */
+
+ if (cv = (name ? GvCV(gv) : Nullcv)) {
+ if (GvCVGEN(gv)) {
+ /* just a cached method */
+ SvREFCNT_dec(cv);
+ cv = 0;
+ }
+ else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
+ /* already defined (or promised) */
if (dowarn) {
line_t oldline = curcop->cop_line;
-
curcop->cop_line = copline;
warn("Subroutine %s redefined",name);
curcop->cop_line = oldline;
cv = 0;
}
}
- if (cv) { /* must reuse cv if autoloaded */
- assert(SvREFCNT(CvGV(cv)) > 1);
- SvREFCNT_dec(CvGV(cv));
- }
+
+ if (cv) /* must reuse cv if autoloaded */
+ cv_undef(cv);
else {
cv = (CV*)NEWSV(1105,0);
sv_upgrade((SV *)cv, SVt_PVCV);
+ if (name) {
+ GvCV(gv) = cv;
+ GvCVGEN(gv) = 0;
+ sub_generation++;
+ }
}
- GvCV(gv) = cv;
- CvGV(cv) = GvREFCNT_inc(gv);
- GvCVGEN(gv) = 0;
+ CvGV(cv) = (GV*)SvREFCNT_inc(gv);
CvFILEGV(cv) = gv_fetchfile(filename);
CvXSUB(cv) = subaddr;
+
if (name) {
char *s = strrchr(name,':');
if (s)
if (strEQ(s, "BEGIN")) {
if (!beginav)
beginav = newAV();
- av_push(beginav, SvREFCNT_inc(gv));
+ av_push(beginav, (SV *)cv);
+ GvCV(gv) = 0;
}
else if (strEQ(s, "END")) {
if (!endav)
endav = newAV();
av_unshift(endav, 1);
- av_store(endav, 0, SvREFCNT_inc(gv));
+ av_store(endav, 0, (SV *)cv);
+ GvCV(gv) = 0;
}
}
- else {
- GvCV(gv) = 0; /* Will remember elsewhere instead. */
+ else
CvANON_on(cv);
- }
+
return cv;
}
}
cv = compcv;
GvFORM(gv) = cv;
- CvGV(cv) = GvREFCNT_inc(gv);
+ CvGV(cv) = (GV*)SvREFCNT_inc(gv);
CvFILEGV(cv) = curcop->cop_filegv;
for (ix = AvFILL(comppad); ix > 0; ix--) {
- if (!SvPADMY(curpad[ix]))
+ if (!SvPADMY(curpad[ix]) && !SvIMMORTAL(curpad[ix]))
SvPADTMP_on(curpad[ix]);
}
CvSTART(cv) = LINKLIST(CvROOT(cv));
CvROOT(cv)->op_next = 0;
peep(CvSTART(cv));
- FmLINES(cv) = 0;
op_free(op);
copline = NOLINE;
LEAVE_SCOPE(floor);
op->op_private |= (hints & HINT_STRICT_REFS);
if (kid->op_type == OP_CONST) {
- int iscv = (op->op_type==OP_RV2CV)*2;
- GV *gv = 0;
+ char *name;
+ int iscv;
+ GV *gv;
+
+ name = SvPV(kid->op_sv, na);
+ if ((hints & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) {
+ char *badthing = Nullch;
+ switch (op->op_type) {
+ case OP_RV2SV:
+ badthing = "a SCALAR";
+ break;
+ case OP_RV2AV:
+ badthing = "an ARRAY";
+ break;
+ case OP_RV2HV:
+ badthing = "a HASH";
+ break;
+ }
+ if (badthing)
+ croak(
+ "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
+ name, badthing);
+ }
kid->op_type = OP_GV;
+ iscv = (op->op_type == OP_RV2CV) * 2;
for (gv = 0; !gv; iscv++) {
/*
* This is a little tricky. We only want to add the symbol if we
* or we get possible typo warnings. OPpCONST_ENTERED says
* whether the lexer already added THIS instance of this symbol.
*/
- gv = gv_fetchpv(SvPVx(kid->op_sv, na),
+ gv = gv_fetchpv(name,
iscv | !(kid->op_private & OPpCONST_ENTERED),
iscv
? SVt_PVCV
OP *newop = newAVREF(newGVOP(OP_GV, 0,
gv_fetchpv(name, TRUE, SVt_PVAV) ));
if (dowarn)
- warn("Array @%s missing the @ in argument %d of %s()",
- name, numargs, op_desc[type]);
+ warn("Array @%s missing the @ in argument %ld of %s()",
+ name, (long)numargs, op_desc[type]);
op_free(kid);
kid = newop;
kid->op_sibling = sibl;
OP *newop = newHVREF(newGVOP(OP_GV, 0,
gv_fetchpv(name, TRUE, SVt_PVHV) ));
if (dowarn)
- warn("Hash %%%s missing the %% in argument %d of %s()",
- name, numargs, op_desc[type]);
+ warn("Hash %%%s missing the %% in argument %ld of %s()",
+ name, (long)numargs, op_desc[type]);
op_free(kid);
kid = newop;
kid->op_sibling = sibl;
newGVOP(OP_GV, 0, gv)))));
return ck_subr(op);
}
+ if ((op->op_flags & OPf_KIDS) && !cLISTOP->op_first->op_sibling)
+ append_elem(OP_GLOB, op, newSVREF(newGVOP(OP_GV, 0, defgv)));
gv = newGVgen("main");
gv_IOadd(gv);
append_elem(OP_GLOB, op, newGVOP(OP_GV, 0, gv));
o->op_seq = op_seqmax++;
break;
case OP_STUB:
- if ((o->op_flags & (OPf_KNOW|OPf_LIST)) != (OPf_KNOW|OPf_LIST)) {
+ if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) {
o->op_seq = op_seqmax++;
- break; /* Scalar stub must produce undef. List stub is noop */
+ break; /* Scalar stub must produce undef. List stub is noop */
}
goto nothin;
case OP_NULL:
if (pop->op_type == OP_CONST &&
(op = pop->op_next) &&
pop->op_next->op_type == OP_AELEM &&
- !(pop->op_next->op_private & (OPpDEREF|OPpLVAL_INTRO)) &&
+ !(pop->op_next->op_private &
+ (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF)) &&
(i = SvIV(((SVOP*)pop)->op_sv) - compiling.cop_arybase)
<= 255 &&
i >= 0)