/* op.c
*
- * Copyright (c) 1991-2003, Larry Wall
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ * 2000, 2001, 2002, 2003, by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
return o;
}
+/* Propagate lvalue ("modifiable") context to an op and it's children.
+ * 'type' represents the context type, roughly based on the type of op that
+ * would do the modifying, although local() is represented by OP_NULL.
+ * It's responsible for detecting things that can't be modified, flag
+ * things that need to behave specially in an lvalue context (e.g., "$$x = 5"
+ * might have to vivify a reference in $x), and so on.
+ *
+ * For example, "$a+1 = 2" would cause mod() to be called with o being
+ * OP_ADD and type being OP_SASSIGN, and would output an error.
+ */
+
OP *
Perl_mod(pTHX_ OP *o, I32 type)
{
OP *kid;
+ /* -1 = error on localize, 0 = ignore localize, 1 = ok to localize */
+ int localize = -1;
if (!o || PL_error_count)
return o;
switch (o->op_type) {
case OP_UNDEF:
+ localize = 0;
PL_modcount++;
return o;
case OP_CONST:
break;
case OP_COND_EXPR:
+ localize = 1;
for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
mod(kid, type);
break;
case OP_HSLICE:
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
+ localize = 1;
/* FALL THROUGH */
case OP_AASSIGN:
case OP_NEXTSTATE:
break;
case OP_RV2SV:
ref(cUNOPo->op_first, o->op_type);
+ localize = 1;
/* FALL THROUGH */
case OP_GV:
case OP_AV2ARYLEN:
case OP_ANDASSIGN:
case OP_ORASSIGN:
case OP_DORASSIGN:
+ PL_modcount++;
+ break;
+
case OP_AELEMFAST:
+ localize = 1;
PL_modcount++;
break;
/* FALL THROUGH */
case OP_PADSV:
PL_modcount++;
- if (!type)
- { /* XXX DAPM 2002.08.25 tmp assert test */
- /* XXX */ assert(av_fetch(PL_comppad_name, (o->op_targ), FALSE));
- /* XXX */ assert(*av_fetch(PL_comppad_name, (o->op_targ), FALSE));
-
+ if (!type) /* local() */
Perl_croak(aTHX_ "Can't localize lexical variable %s",
PAD_COMPNAME_PV(o->op_targ));
- }
break;
case OP_PUSHMARK:
+ localize = 0;
break;
case OP_KEYS:
o->op_private |= OPpLVAL_DEFER;
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
+ localize = 1;
PL_modcount++;
break;
case OP_LEAVE:
case OP_ENTER:
case OP_LINESEQ:
+ localize = 0;
if (o->op_flags & OPf_KIDS)
mod(cLISTOPo->op_last, type);
break;
case OP_NULL:
+ localize = 0;
if (o->op_flags & OPf_SPECIAL) /* do BLOCK */
goto nomod;
else if (!(o->op_flags & OPf_KIDS))
}
/* FALL THROUGH */
case OP_LIST:
+ localize = 0;
for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
mod(kid, type);
break;
if (type == OP_AASSIGN || type == OP_SASSIGN)
o->op_flags |= OPf_SPECIAL|OPf_REF;
- else if (!type) {
- o->op_private |= OPpLVAL_INTRO;
- o->op_flags &= ~OPf_SPECIAL;
- PL_hints |= HINT_BLOCK_SCOPE;
+ else if (!type) { /* local() */
+ switch (localize) {
+ case 1:
+ o->op_private |= OPpLVAL_INTRO;
+ o->op_flags &= ~OPf_SPECIAL;
+ PL_hints |= HINT_BLOCK_SCOPE;
+ break;
+ case 0:
+ break;
+ case -1:
+ if (ckWARN(WARN_SYNTAX)) {
+ Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
+ "Useless localization of %s", OP_DESC(o));
+ }
+ }
}
else if (type != OP_GREPSTART && type != OP_ENTERSUB
&& type != OP_LEAVESUBLV)
&& PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',')
{
char *s = PL_bufptr;
+ int sigil = 0;
- while (*s && (isALNUM(*s) || UTF8_IS_CONTINUED(*s) || strchr("@$%, ", *s)))
+ /* some heuristics to detect a potential error */
+ while (*s && (strchr(", \t\n", *s)
+ || (strchr("@$%*", *s) && ++sigil) ))
s++;
-
- if (*s == ';' || *s == '=')
- Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS),
- "Parentheses missing around \"%s\" list",
- lex ? (PL_in_my == KEY_our ? "our" : "my") : "local");
+ if (sigil) {
+ while (*s && (isALNUM(*s) || UTF8_IS_CONTINUED(*s)
+ || strchr("@$%*, \t\n", *s)))
+ s++;
+
+ if (*s == ';' || *s == '=')
+ Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS),
+ "Parentheses missing around \"%s\" list",
+ lex ? (PL_in_my == KEY_our ? "our" : "my")
+ : "local");
+ }
}
}
if (lex)
}
void
-Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg)
+Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
{
OP *pack;
OP *imop;
OP *veop;
- if (id->op_type != OP_CONST)
+ if (idop->op_type != OP_CONST)
Perl_croak(aTHX_ "Module name must be constant");
veop = Nullop;
if (version->op_type != OP_CONST || !SvNIOKp(vesv))
Perl_croak(aTHX_ "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));
+ /* Make copy of idop so we don't free it twice */
+ pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv));
/* Fake up a method call to VERSION */
meth = newSVpvn("VERSION",7);
/* Fake up an import/unimport */
if (arg && arg->op_type == OP_STUB)
imop = arg; /* no import on explicit () */
- else if (SvNIOKp(((SVOP*)id)->op_sv)) {
+ else if (SvNIOKp(((SVOP*)idop)->op_sv)) {
imop = Nullop; /* use 5.0; */
}
else {
SV *meth;
- /* Make copy of id so we don't free it twice */
- pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv));
+ /* Make copy of idop so we don't free it twice */
+ pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv));
/* Fake up a method call to import/unimport */
meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);
Nullop,
append_elem(OP_LINESEQ,
append_elem(OP_LINESEQ,
- newSTATEOP(0, Nullch, newUNOP(OP_REQUIRE, 0, id)),
+ newSTATEOP(0, Nullch, newUNOP(OP_REQUIRE, 0, idop)),
newSTATEOP(0, Nullch, veop)),
newSTATEOP(0, Nullch, imop) ));
if (!next)
next = unstack;
cont = append_elem(OP_LINESEQ, cont, unstack);
- if ((line_t)whileline != NOLINE) {
- PL_copline = (line_t)whileline;
- cont = append_elem(OP_LINESEQ, cont,
- newSTATEOP(0, Nullch, Nullop));
- }
}
listop = append_list(OP_LINESEQ, (LISTOP*)block, (LISTOP*)cont);
OP *wop;
PADOFFSET padoff = 0;
I32 iterflags = 0;
+ I32 iterpflags = 0;
if (sv) {
if (sv->op_type == OP_RV2SV) { /* symbol table variable */
+ iterpflags = sv->op_private & OPpOUR_INTRO; /* for our $x () */
sv->op_type = OP_RV2GV;
sv->op_ppaddr = PL_ppaddr[OP_RV2GV];
}
else if (sv->op_type == OP_PADSV) { /* private variable */
+ iterpflags = sv->op_private & OPpLVAL_INTRO; /* for my $x () */
padoff = sv->op_targ;
sv->op_targ = 0;
op_free(sv);
loop = (LOOP*)list(convert(OP_ENTERITER, iterflags,
append_elem(OP_LIST, expr, scalar(sv))));
assert(!loop->op_next);
+ /* for my $x () sets OPpLVAL_INTRO;
+ * for our $x () sets OPpOUR_INTRO; both only used by Deparse.pm */
+ loop->op_private = iterpflags;
#ifdef PL_OP_SLAB_ALLOC
{
LOOP *tmp;
CopSTASH_set(PL_curcop,stash);
}
- cv = newXS(name, const_sv_xsub, CopFILE(PL_curcop));
+ cv = newXS(name, const_sv_xsub, savepv(CopFILE(PL_curcop)));
CvXSUBANY(cv).any_ptr = sv;
CvCONST_on(cv);
sv_setpv((SV*)cv, ""); /* prototype is "" */
|| o->op_type == OP_BIT_AND
|| o->op_type == OP_BIT_XOR)
{
- OPCODE typfirst = cBINOPo->op_first->op_type;
- OPCODE typlast = cBINOPo->op_first->op_sibling->op_type;
- if (OP_IS_NUMCOMPARE(typfirst) || OP_IS_NUMCOMPARE(typlast))
+ OP * left = cBINOPo->op_first;
+ OP * right = left->op_sibling;
+ if ((OP_IS_NUMCOMPARE(left->op_type) &&
+ (left->op_flags & OPf_PARENS) == 0) ||
+ (OP_IS_NUMCOMPARE(right->op_type) &&
+ (right->op_flags & OPf_PARENS) == 0))
if (ckWARN(WARN_PRECEDENCE))
Perl_warner(aTHX_ packWARN(WARN_PRECEDENCE),
"Possible precedence problem on bitwise %c operator",
op_free(o);
o = newop;
}
+ else {
+ if ((PL_hints & HINT_FILETEST_ACCESS) &&
+ OP_IS_FILETEST_ACCESS(o))
+ o->op_private |= OPpFT_ACCESS;
+ }
}
else {
op_free(o);
*/
priv = OPpDEREF;
if (kid->op_type == OP_PADSV) {
- /*XXX DAPM 2002.08.25 tmp assert test */
- /*XXX*/ assert(av_fetch(PL_comppad_name, (kid->op_targ), FALSE));
- /*XXX*/ assert(*av_fetch(PL_comppad_name, (kid->op_targ), FALSE));
-
name = PAD_COMPNAME_PV(kid->op_targ);
/* SvCUR of a pad namesv can't be trusted
* (see PL_generation), so calc its length