/* op.c
*
- * Copyright (c) 1991-1999, Larry Wall
+ * Copyright (c) 1991-2000, 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.
/* #define PL_OP_SLAB_ALLOC */
/* XXXXXX testing */
-#define OP_REFCNT_LOCK NOOP
-#define OP_REFCNT_UNLOCK NOOP
-#define OpREFCNT_set(o,n) NOOP
-#define OpREFCNT_dec(o) ((o)->op_targ--)
+#ifdef USE_ITHREADS
+# define OP_REFCNT_LOCK NOOP
+# define OP_REFCNT_UNLOCK NOOP
+# define OpREFCNT_set(o,n) ((o)->op_targ = (n))
+# define OpREFCNT_dec(o) (--(o)->op_targ)
+#else
+# define OP_REFCNT_LOCK NOOP
+# define OP_REFCNT_UNLOCK NOOP
+# define OpREFCNT_set(o,n) NOOP
+# define OpREFCNT_dec(o) 0
+#endif
#ifdef PL_OP_SLAB_ALLOC
#define SLAB_SIZE 8192
}
yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
}
- if (ckWARN(WARN_UNSAFE) && AvFILLp(PL_comppad_name) >= 0) {
+ if (ckWARN(WARN_MISC) && AvFILLp(PL_comppad_name) >= 0) {
SV **svp = AvARRAY(PL_comppad_name);
- for (off = AvFILLp(PL_comppad_name); off > PL_comppad_name_floor; off--) {
+ HV *ourstash = (PL_curstash ? PL_curstash : PL_defstash);
+ PADOFFSET top = AvFILLp(PL_comppad_name);
+ for (off = top; off > PL_comppad_name_floor; off--) {
if ((sv = svp[off])
&& sv != &PL_sv_undef
&& (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
+ && (PL_in_my != KEY_our
+ || ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash))
&& strEQ(name, SvPVX(sv)))
{
- Perl_warner(aTHX_ WARN_UNSAFE,
- "\"%s\" variable %s masks earlier declaration in same %s",
- (PL_in_my == KEY_our ? "our" : "my"),
- name,
- (SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
+ Perl_warner(aTHX_ WARN_MISC,
+ "\"%s\" variable %s masks earlier declaration in same %s",
+ (PL_in_my == KEY_our ? "our" : "my"),
+ name,
+ (SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
+ --off;
break;
}
}
+ if (PL_in_my == KEY_our) {
+ while (off >= 0 && off <= top) {
+ if ((sv = svp[off])
+ && sv != &PL_sv_undef
+ && ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash)
+ && strEQ(name, SvPVX(sv)))
+ {
+ Perl_warner(aTHX_ WARN_MISC,
+ "\"our\" variable %s redeclared", name);
+ Perl_warner(aTHX_ WARN_MISC,
+ "(Did you mean \"local\" instead of \"our\"?)\n");
+ break;
+ }
+ --off;
+ }
+ }
}
off = pad_alloc(OP_PADSV, SVs_PADMY);
sv = NEWSV(1102,0);
sv_setpv(sv, name);
if (PL_in_my_stash) {
if (*name != '$')
- yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"my\"",
- name));
+ yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"",
+ name, PL_in_my == KEY_our ? "our" : "my"));
SvOBJECT_on(sv);
(void)SvUPGRADE(sv, SVt_PVMG);
SvSTASH(sv) = (HV*)SvREFCNT_inc(PL_in_my_stash);
PL_sv_objcount++;
}
- if (PL_in_my == KEY_our)
+ if (PL_in_my == KEY_our) {
+ (void)SvUPGRADE(sv, SVt_PVGV);
+ GvSTASH(sv) = (HV*)SvREFCNT_inc(PL_curstash ? PL_curstash : PL_defstash);
SvFLAGS(sv) |= SVpad_OUR;
+ }
av_store(PL_comppad_name, off, sv);
SvNVX(sv) = (NV)PAD_MAX;
SvIVX(sv) = 0; /* Not yet introduced--see newSTATEOP */
return off;
}
+STATIC PADOFFSET
+S_pad_addlex(pTHX_ SV *proto_namesv)
+{
+ SV *namesv = NEWSV(1103,0);
+ PADOFFSET newoff = pad_alloc(OP_PADSV, SVs_PADMY);
+ sv_upgrade(namesv, SVt_PVNV);
+ sv_setpv(namesv, SvPVX(proto_namesv));
+ av_store(PL_comppad_name, newoff, namesv);
+ SvNVX(namesv) = (NV)PL_curcop->cop_seq;
+ SvIVX(namesv) = PAD_MAX; /* A ref, intro immediately */
+ SvFAKE_on(namesv); /* A ref, not a real var */
+ if (SvFLAGS(proto_namesv) & SVpad_OUR) { /* An "our" variable */
+ SvFLAGS(namesv) |= SVpad_OUR;
+ (void)SvUPGRADE(namesv, SVt_PVGV);
+ GvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)GvSTASH(proto_namesv));
+ }
+ if (SvOBJECT(proto_namesv)) { /* A typed var */
+ SvOBJECT_on(namesv);
+ (void)SvUPGRADE(namesv, SVt_PVMG);
+ SvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)SvSTASH(proto_namesv));
+ PL_sv_objcount++;
+ }
+ return newoff;
+}
+
#define FINDLEX_NOSEARCH 1 /* don't search outer contexts */
STATIC PADOFFSET
}
depth = 1;
}
- oldpad = (AV*)*av_fetch(curlist, depth, FALSE);
+ oldpad = (AV*)AvARRAY(curlist)[depth];
oldsv = *av_fetch(oldpad, off, TRUE);
if (!newoff) { /* Not a mere clone operation. */
- SV *namesv = NEWSV(1103,0);
- newoff = pad_alloc(OP_PADSV, SVs_PADMY);
- sv_upgrade(namesv, SVt_PVNV);
- sv_setpv(namesv, name);
- av_store(PL_comppad_name, newoff, namesv);
- SvNVX(namesv) = (NV)PL_curcop->cop_seq;
- SvIVX(namesv) = PAD_MAX; /* A ref, intro immediately */
- SvFAKE_on(namesv); /* A ref, not a real var */
- if (SvFLAGS(sv) & SVpad_OUR)/* An "our" variable */
- SvFLAGS(namesv) |= SVpad_OUR;
- if (SvOBJECT(sv)) { /* A typed var */
- SvOBJECT_on(namesv);
- (void)SvUPGRADE(namesv, SVt_PVMG);
- SvSTASH(namesv) = (HV*)SvREFCNT_inc((SV*)SvSTASH(sv));
- PL_sv_objcount++;
- }
+ newoff = pad_addlex(sv);
if (CvANON(PL_compcv) || SvTYPE(PL_compcv) == SVt_PVFM) {
/* "It's closures all the way down." */
CvCLONE_on(PL_compcv);
bcv && bcv != cv && !CvCLONE(bcv);
bcv = CvOUTSIDE(bcv))
{
- if (CvANON(bcv))
+ if (CvANON(bcv)) {
+ /* install the missing pad entry in intervening
+ * nested subs and mark them cloneable.
+ * XXX fix pad_foo() to not use globals */
+ AV *ocomppad_name = PL_comppad_name;
+ AV *ocomppad = PL_comppad;
+ SV **ocurpad = PL_curpad;
+ AV *padlist = CvPADLIST(bcv);
+ PL_comppad_name = (AV*)AvARRAY(padlist)[0];
+ PL_comppad = (AV*)AvARRAY(padlist)[1];
+ PL_curpad = AvARRAY(PL_comppad);
+ pad_addlex(sv);
+ PL_comppad_name = ocomppad_name;
+ PL_comppad = ocomppad;
+ PL_curpad = ocurpad;
CvCLONE_on(bcv);
+ }
else {
if (ckWARN(WARN_CLOSURE)
&& !CvUNIQUE(bcv) && !CvUNIQUE(cv))
DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%"UVxf" free %"IVdf"\n",
PTR2UV(PL_curpad), (IV)po));
#endif /* USE_THREADS */
- if (PL_curpad[po] && PL_curpad[po] != &PL_sv_undef)
+ if (PL_curpad[po] && PL_curpad[po] != &PL_sv_undef) {
SvPADTMP_off(PL_curpad[po]);
+#ifdef USE_ITHREADS
+ SvREADONLY_off(PL_curpad[po]); /* could be a freed constant */
+#endif
+ }
if ((I32)po < PL_padix)
PL_padix = po - 1;
}
OP_REFCNT_UNLOCK;
return;
}
- o->op_targ = 0; /* XXXXXX */
OP_REFCNT_UNLOCK;
break;
default:
case OP_GGRGID:
case OP_GETLOGIN:
func_ops:
- if (!(o->op_private & OPpLVAL_INTRO))
+ if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)))
useless = PL_op_desc[o->op_type];
break;
case OP_RV2SV:
case OP_RV2AV:
case OP_RV2HV:
- if (!(o->op_private & OPpLVAL_INTRO) &&
+ if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)) &&
(!o->op_sibling || o->op_sibling->op_type != OP_READLINE))
useless = "a variable";
break;
if (kid->op_type == OP_METHOD_NAMED
|| kid->op_type == OP_METHOD)
{
- OP *newop;
+ UNOP *newop;
if (kid->op_sibling || kid->op_next != kid) {
yyerror("panic: unexpected optree near method call");
break;
}
- NewOp(1101, newop, 1, OP);
+ NewOp(1101, newop, 1, UNOP);
newop->op_type = OP_RV2CV;
newop->op_ppaddr = PL_ppaddr[OP_RV2CV];
- newop->op_next = newop;
- kid->op_sibling = newop;
+ newop->op_first = Nullop;
+ newop->op_next = (OP*)newop;
+ kid->op_sibling = (OP*)newop;
newop->op_private |= OPpLVAL_INTRO;
break;
}
switch (o->op_type) {
case OP_ENTERSUB:
- if ((type == OP_DEFINED || type == OP_LOCK) &&
+ if ((type == OP_EXISTS || type == OP_DEFINED || type == OP_LOCK) &&
!(o->op_flags & OPf_STACKED)) {
o->op_type = OP_RV2CV; /* entersub => rv2cv */
o->op_ppaddr = PL_ppaddr[OP_RV2CV];
} else if (type == OP_RV2SV || /* "our" declaration */
type == OP_RV2AV ||
type == OP_RV2HV) { /* XXX does this let anything illegal in? */
+ o->op_private |= OPpOUR_INTRO;
return o;
} else if (type != OP_PADSV &&
type != OP_PADAV &&
type != OP_PADHV &&
type != OP_PUSHMARK)
{
- yyerror(Perl_form(aTHX_ "Can't declare %s in my", PL_op_desc[o->op_type]));
+ yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
+ PL_op_desc[o->op_type],
+ PL_in_my == KEY_our ? "our" : "my"));
return o;
}
else if (attrs && type != OP_PUSHMARK) {
SV *padsv;
SV **namesvp;
+ PL_in_my = FALSE;
+ PL_in_my_stash = Nullhv;
+
/* check for C<my Dog $spot> when deciding package */
namesvp = av_fetch(PL_comppad_name, o->op_targ, FALSE);
if (namesvp && *namesvp && SvOBJECT(*namesvp) && HvNAME(SvSTASH(*namesvp)))
{
if (o->op_flags & OPf_PARENS)
list(o);
- PL_in_my = FALSE;
- PL_in_my_stash = Nullhv;
if (attrs)
SAVEFREEOP(attrs);
- return my_kid(o, attrs);
+ o = my_kid(o, attrs);
+ PL_in_my = FALSE;
+ PL_in_my_stash = Nullhv;
+ return o;
}
OP *
dTHR;
OP *o;
- if (ckWARN(WARN_UNSAFE) &&
+ if (ckWARN(WARN_MISC) &&
(left->op_type == OP_RV2AV ||
left->op_type == OP_RV2HV ||
left->op_type == OP_PADAV ||
const char *sample = ((left->op_type == OP_RV2AV ||
left->op_type == OP_PADAV)
? "@array" : "%hash");
- Perl_warner(aTHX_ WARN_UNSAFE,
+ Perl_warner(aTHX_ WARN_MISC,
"Applying %s to %s will act on scalar(%s)",
desc, sample, sample);
}
int retval = PL_savestack_ix;
SAVEI32(PL_comppad_name_floor);
- if (full) {
- if ((PL_comppad_name_fill = AvFILLp(PL_comppad_name)) > 0)
- PL_comppad_name_floor = PL_comppad_name_fill;
- else
- PL_comppad_name_floor = 0;
- }
+ PL_comppad_name_floor = AvFILLp(PL_comppad_name);
+ if (full)
+ PL_comppad_name_fill = PL_comppad_name_floor;
+ if (PL_comppad_name_floor < 0)
+ PL_comppad_name_floor = 0;
SAVEI32(PL_min_intro_pending);
SAVEI32(PL_max_intro_pending);
PL_min_intro_pending = 0;
PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
SAVEFREESV(PL_compiling.cop_warnings) ;
}
-
-
return retval;
}
char *s;
for (s = PL_bufptr; *s && (isALNUM(*s) || (*s & 0x80) || strchr("@$%, ",*s)); s++) ;
if (*s == ';' || *s == '=')
- Perl_warner(aTHX_ WARN_PARENTHESIS, "Parentheses missing around \"%s\" list",
- lex ? "my" : "local");
+ Perl_warner(aTHX_ WARN_PARENTHESIS,
+ "Parentheses missing around \"%s\" list",
+ lex ? (PL_in_my == KEY_our ? "our" : "my") : "local");
}
}
- PL_in_my = FALSE;
- PL_in_my_stash = Nullhv;
if (lex)
- return my(o);
+ o = my(o);
else
- return mod(o, OP_NULL); /* a bit kludgey */
+ o = mod(o, OP_NULL); /* a bit kludgey */
+ PL_in_my = FALSE;
+ PL_in_my_stash = Nullhv;
+ return o;
}
OP *
PL_op = curop = LINKLIST(o);
o->op_next = 0;
+ peep(curop);
pp_pushmark();
CALLRUNOPS(aTHX);
PL_op = curop;
if (rfirst == 0xffffffff) {
diff = tdiff; /* oops, pretend rdiff is infinite */
if (diff > 0)
- Perl_sv_catpvf(aTHX_ listsv, "%04x\t%04x\tXXXX\n", tfirst, tlast);
+ Perl_sv_catpvf(aTHX_ listsv, "%04lx\t%04lx\tXXXX\n",
+ (long)tfirst, (long)tlast);
else
- Perl_sv_catpvf(aTHX_ listsv, "%04x\t\tXXXX\n", tfirst);
+ Perl_sv_catpvf(aTHX_ listsv, "%04lx\t\tXXXX\n", (long)tfirst);
}
else {
if (diff > 0)
- Perl_sv_catpvf(aTHX_ listsv, "%04x\t%04x\t%04x\n", tfirst, tfirst + diff, rfirst);
+ Perl_sv_catpvf(aTHX_ listsv, "%04lx\t%04lx\t%04lx\n",
+ (long)tfirst, (long)(tfirst + diff),
+ (long)rfirst);
else
- Perl_sv_catpvf(aTHX_ listsv, "%04x\t\t%04x\n", tfirst, rfirst);
+ Perl_sv_catpvf(aTHX_ listsv, "%04lx\t\t%04lx\n",
+ (long)tfirst, (long)rfirst);
if (rfirst + diff > max)
max = rfirst + diff;
p = SvPV(pat, plen);
pm->op_pmflags |= PMf_SKIPWHITE;
}
+ if ((PL_hints & HINT_UTF8) || (SvUTF8(pat) && !(PL_hints & HINT_BYTE)))
+ pm->op_pmdynflags |= PMdf_UTF8;
pm->op_pmregexp = CALLREGCOMP(aTHX_ p, p + plen, pm);
if (strEQ("\\s+", pm->op_pmregexp->precomp))
pm->op_pmflags |= PMf_WHITE;
op_free(expr);
}
else {
+ if (PL_hints & HINT_UTF8)
+ pm->op_pmdynflags |= PMdf_UTF8;
if (pm->op_pmflags & PMf_KEEP || !(PL_hints & HINT_RE_EVAL))
expr = newUNOP((!(PL_hints & HINT_RE_EVAL)
? OP_REGCRESET
veop = Nullop;
- if(version != Nullop) {
+ if (version != Nullop) {
SV *vesv = ((SVOP*)version)->op_sv;
- if (arg == Nullop && !SvNIOK(vesv)) {
+ if (arg == Nullop && !SvNIOKp(vesv)) {
arg = version;
}
else {
OP *pack;
+ SV *meth;
- if (version->op_type != OP_CONST || !SvNIOK(vesv))
+ 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));
/* Fake up a method call to VERSION */
+ meth = newSVpvn("VERSION",7);
+ sv_upgrade(meth, SVt_PVIV);
+ SvIOK_on(meth);
+ PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
append_elem(OP_LIST,
- prepend_elem(OP_LIST, pack, list(version)),
- newSVOP(OP_METHOD_NAMED, 0,
- newSVpvn("VERSION", 7))));
+ prepend_elem(OP_LIST, pack, list(version)),
+ newSVOP(OP_METHOD_NAMED, 0, meth)));
}
}
/* Fake up an import/unimport */
if (arg && arg->op_type == OP_STUB)
imop = arg; /* no import on explicit () */
- else if(SvNIOK(((SVOP*)id)->op_sv)) {
+ else if (SvNIOKp(((SVOP*)id)->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));
+
+ /* Fake up a method call to import/unimport */
+ meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);;
+ sv_upgrade(meth, SVt_PVIV);
+ SvIOK_on(meth);
+ PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
- append_elem(OP_LIST,
- prepend_elem(OP_LIST, pack, list(arg)),
- newSVOP(OP_METHOD_NAMED, 0,
- aver ? newSVpvn("import", 6)
- : newSVpvn("unimport", 8))));
+ append_elem(OP_LIST,
+ prepend_elem(OP_LIST, pack, list(arg)),
+ newSVOP(OP_METHOD_NAMED, 0, meth)));
}
/* Fake up a require, handle override, if any */
cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ];
}
cop->op_flags = flags;
- cop->op_private = (PL_hints & HINT_UTF8);
+ cop->op_private = (PL_hints & HINT_BYTE);
#ifdef NATIVE_HINTS
cop->op_private |= NATIVE_HINTS;
#endif
}
}
if (first->op_type == OP_CONST) {
- if (ckWARN(WARN_PRECEDENCE) && (first->op_private & OPpCONST_BARE))
- Perl_warner(aTHX_ WARN_PRECEDENCE, "Probable precedence problem on %s",
- PL_op_desc[type]);
+ if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE))
+ Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional");
if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
op_free(first);
*firstp = Nullop;
else
scalar(other);
}
- else if (ckWARN(WARN_UNSAFE) && (first->op_flags & OPf_KIDS)) {
+ else if (ckWARN(WARN_MISC) && (first->op_flags & OPf_KIDS)) {
OP *k1 = ((UNOP*)first)->op_first;
OP *k2 = k1->op_sibling;
OPCODE warnop = 0;
if (warnop) {
line_t oldline = CopLINE(PL_curcop);
CopLINE_set(PL_curcop, PL_copline);
- Perl_warner(aTHX_ WARN_UNSAFE,
+ Perl_warner(aTHX_ WARN_MISC,
"Value of %s%s can be \"0\"; test with defined()",
PL_op_desc[warnop],
((warnop == OP_READLINE || warnop == OP_GLOB)
if (!block)
block = newOP(OP_NULL, 0);
+ else if (cont) {
+ block = scope(block);
+ }
if (cont)
next = LINKLIST(cont);
if (SvPOK(pname[ix]))
PerlIO_printf(Perl_debug_log,
"\t%4d. 0x%"UVxf" (%s\"%s\" %"IVdf"-%"IVdf")\n",
- ix, PTR2UV(ppad[ix]),
+ (int)ix, PTR2UV(ppad[ix]),
SvFAKE(pname[ix]) ? "FAKE " : "",
SvPVX(pname[ix]),
(IV)I_32(SvNVX(pname[ix])),
assert(!CvUNIQUE(proto));
ENTER;
- SAVEVPTR(PL_curpad);
- SAVESPTR(PL_comppad);
+ SAVECOMPPAD();
SAVESPTR(PL_comppad_name);
SAVESPTR(PL_compcv);
Perl_cv_clone(pTHX_ CV *proto)
{
CV *cv;
- MUTEX_LOCK(&PL_cred_mutex); /* XXX create separate mutex */
+ LOCK_CRED_MUTEX; /* XXX create separate mutex */
cv = cv_clone2(proto, CvOUTSIDE(proto));
- MUTEX_UNLOCK(&PL_cred_mutex); /* XXX create separate mutex */
+ UNLOCK_CRED_MUTEX; /* XXX create separate mutex */
return cv;
}
{
dTHR;
- if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_UNSAFE)) {
+ if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_PROTOTYPE)) {
SV* msg = sv_newmortal();
SV* name = Nullsv;
gv_efullname3(name = sv_newmortal(), gv, Nullch);
sv_setpv(msg, "Prototype mismatch:");
if (name)
- Perl_sv_catpvf(aTHX_ msg, " sub %_", name);
+ Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name);
if (SvPOK(cv))
Perl_sv_catpvf(aTHX_ msg, " (%s)", SvPVX(cv));
sv_catpv(msg, " vs ");
Perl_sv_catpvf(aTHX_ msg, "(%s)", p);
else
sv_catpv(msg, "none");
- Perl_warner(aTHX_ WARN_UNSAFE, "%_", msg);
+ Perl_warner(aTHX_ WARN_PROTOTYPE, "%"SVf, msg);
}
}
{
SV *sv = Nullsv;
- if(!o)
+ if (!o)
return Nullsv;
- if(o->op_type == OP_LINESEQ && cLISTOPo->op_first)
+ if (o->op_type == OP_LINESEQ && cLISTOPo->op_first)
o = cLISTOPo->op_first->op_sibling;
for (; o; o = o->op_next) {
{
dTHR;
STRLEN n_a;
- char *name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
- GV *gv = gv_fetchpv(name ? name : "__ANON__",
- GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT),
- SVt_PVCV);
+ char *name;
+ char *aname;
+ GV *gv;
char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch;
register CV *cv=0;
I32 ix;
+ name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
+ if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) {
+ SV *sv = sv_newmortal();
+ Perl_sv_setpvf(aTHX_ sv, "__ANON__[%s:%"IVdf"]",
+ CopFILE(PL_curcop), (IV)CopLINE(PL_curcop));
+ aname = SvPVX(sv);
+ }
+ else
+ aname = Nullch;
+ gv = gv_fetchpv(name ? name : (aname ? aname : "__ANON__"),
+ GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT),
+ SVt_PVCV);
+
if (o)
SAVEFREEOP(o);
if (proto)
maximum a prototype before. */
if (SvTYPE(gv) > SVt_NULL) {
if (!SvPOK((SV*)gv) && !(SvIOK((SV*)gv) && SvIVX((SV*)gv) == -1)
- && ckWARN_d(WARN_UNSAFE))
+ && ckWARN_d(WARN_PROTOTYPE))
{
- Perl_warner(aTHX_ WARN_UNSAFE, "Runaway prototype");
+ Perl_warner(aTHX_ WARN_PROTOTYPE, "Runaway prototype");
}
cv_ckproto((CV*)gv, NULL, ps);
}
Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name);
if (!block)
goto withattrs;
- if(const_sv = cv_const_sv(cv))
+ if (const_sv = cv_const_sv(cv))
const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv));
- if ((const_sv && const_changed) || ckWARN(WARN_REDEFINE)
- && !(CvGV(cv) && GvSTASH(CvGV(cv))
- && HvNAME(GvSTASH(CvGV(cv)))
- && strEQ(HvNAME(GvSTASH(CvGV(cv))),
- "autouse"))) {
+ if ((const_sv || const_changed) && ckWARN(WARN_REDEFINE))
+ {
line_t oldline = CopLINE(PL_curcop);
CopLINE_set(PL_curcop, PL_copline);
Perl_warner(aTHX_ WARN_REDEFINE,
}
}
- if (name) {
+ if (name || aname) {
char *s;
+ char *tname = (name ? name : aname);
if (PERLDB_SUBLINE && PL_curstash != PL_debstash) {
SV *sv = NEWSV(0,0);
SV *tmpstr = sv_newmortal();
GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV);
- CV *cv;
+ CV *pcv;
HV *hv;
+ char *t;
Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld",
CopFILE(PL_curcop),
hv_store(GvHV(PL_DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0);
hv = GvHVn(db_postponed);
if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr))
- && (cv = GvCV(db_postponed))) {
+ && (pcv = GvCV(db_postponed)))
+ {
dSP;
PUSHMARK(SP);
XPUSHs(tmpstr);
PUTBACK;
- call_sv((SV*)cv, G_DISCARD);
+ call_sv((SV*)pcv, G_DISCARD);
}
}
- if ((s = strrchr(name,':')))
+ if ((s = strrchr(tname,':')))
s++;
else
- s = name;
+ s = tname;
- if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I')
+ if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
goto done;
if (strEQ(s, "BEGIN")) {
av_store(PL_endav, 0, SvREFCNT_inc(cv));
GvCV(gv) = 0;
}
- else if (strEQ(s, "STOP") && !PL_error_count) {
- if (!PL_stopav)
- PL_stopav = newAV();
+ else if (strEQ(s, "CHECK") && !PL_error_count) {
+ if (!PL_checkav)
+ PL_checkav = newAV();
DEBUG_x( dump_sub(gv) );
- av_unshift(PL_stopav, 1);
- av_store(PL_stopav, 0, SvREFCNT_inc(cv));
+ av_unshift(PL_checkav, 1);
+ av_store(PL_checkav, 0, SvREFCNT_inc(cv));
GvCV(gv) = 0;
}
else if (strEQ(s, "INIT") && !PL_error_count) {
}
/* XXX unsafe for threads if eval_owner isn't held */
+/*
+=for apidoc newCONSTSUB
+
+Creates a constant sub equivalent to Perl C<sub FOO () { 123 }> which is
+eligible for inlining at compile-time.
+
+=cut
+*/
+
void
Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
{
LEAVE;
}
+/*
+=for apidoc U||newXS
+
+Used by C<xsubpp> to hook up XSUBs as Perl subs.
+
+=cut
+*/
+
CV *
Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
{
else
s = name;
- if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I')
+ if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
goto done;
if (strEQ(s, "BEGIN")) {
av_store(PL_endav, 0, SvREFCNT_inc(cv));
GvCV(gv) = 0;
}
- else if (strEQ(s, "STOP")) {
- if (!PL_stopav)
- PL_stopav = newAV();
- av_unshift(PL_stopav, 1);
- av_store(PL_stopav, 0, SvREFCNT_inc(cv));
+ else if (strEQ(s, "CHECK")) {
+ if (!PL_checkav)
+ PL_checkav = newAV();
+ av_unshift(PL_checkav, 1);
+ av_store(PL_checkav, 0, SvREFCNT_inc(cv));
GvCV(gv) = 0;
}
else if (strEQ(s, "INIT")) {
o->op_private = 0;
if (o->op_flags & OPf_KIDS) {
OP *kid = cUNOPo->op_first;
- if (kid->op_type == OP_HSLICE)
+ switch (kid->op_type) {
+ case OP_ASLICE:
+ o->op_flags |= OPf_SPECIAL;
+ /* FALL THROUGH */
+ case OP_HSLICE:
o->op_private |= OPpSLICE;
- else if (kid->op_type != OP_HELEM)
- Perl_croak(aTHX_ "%s argument is not a HASH element or slice",
+ break;
+ case OP_AELEM:
+ o->op_flags |= OPf_SPECIAL;
+ /* FALL THROUGH */
+ case OP_HELEM:
+ break;
+ default:
+ Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element or slice",
PL_op_desc[o->op_type]);
+ }
null(kid);
}
return o;
o = ck_fun(o);
if (o->op_flags & OPf_KIDS) {
OP *kid = cUNOPo->op_first;
- if (kid->op_type != OP_HELEM)
- Perl_croak(aTHX_ "%s argument is not a HASH element", PL_op_desc[o->op_type]);
+ if (kid->op_type == OP_ENTERSUB) {
+ (void) ref(kid, o->op_type);
+ if (kid->op_type != OP_RV2CV && !PL_error_count)
+ Perl_croak(aTHX_ "%s argument is not a subroutine name",
+ PL_op_desc[o->op_type]);
+ o->op_private |= OPpEXISTS_SUB;
+ }
+ else if (kid->op_type == OP_AELEM)
+ o->op_flags |= OPf_SPECIAL;
+ else if (kid->op_type != OP_HELEM)
+ Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element",
+ PL_op_desc[o->op_type]);
null(kid);
}
return o;
char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
OP *newop = newAVREF(newGVOP(OP_GV, 0,
gv_fetchpv(name, TRUE, SVt_PVAV) ));
- if (ckWARN(WARN_SYNTAX))
- Perl_warner(aTHX_ WARN_SYNTAX,
+ if (ckWARN(WARN_DEPRECATED))
+ Perl_warner(aTHX_ WARN_DEPRECATED,
"Array @%s missing the @ in argument %"IVdf" of %s()",
name, (IV)numargs, PL_op_desc[type]);
op_free(kid);
char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
OP *newop = newHVREF(newGVOP(OP_GV, 0,
gv_fetchpv(name, TRUE, SVt_PVHV) ));
- if (ckWARN(WARN_SYNTAX))
- Perl_warner(aTHX_ WARN_SYNTAX,
+ if (ckWARN(WARN_DEPRECATED))
+ Perl_warner(aTHX_ WARN_DEPRECATED,
"Hash %%%s missing the %% in argument %"IVdf" of %s()",
name, (IV)numargs, PL_op_desc[type]);
op_free(kid);
{
GV *gv;
+ o = ck_fun(o);
if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling)
append_elem(OP_GLOB, o, newDEFSVOP());
gv_IOadd(gv);
append_elem(OP_GLOB, o, newGVOP(OP_GV, 0, gv));
scalarkids(o);
- return ck_fun(o);
+ return o;
}
OP *
break; /* Globals via GV can be undef */
case OP_PADHV:
Perl_warner(aTHX_ WARN_DEPRECATED,
- "defined(%hash) is deprecated");
+ "defined(%%hash) is deprecated");
Perl_warner(aTHX_ WARN_DEPRECATED,
"(Maybe you should just omit the defined()?)\n");
break;
OP *kid = cLISTOPo->op_first;
/* has a disposable target? */
if ((PL_opargs[kid->op_type] & OA_TARGLEX)
- && !(kid->op_flags & OPf_STACKED))
+ && !(kid->op_flags & OPf_STACKED)
+ /* Cannot steal the second time! */
+ && !(kid->op_private & OPpTARGET_MY))
{
OP *kkid = kid->op_sibling;
if (kkid && kkid->op_type == OP_PADSV
&& !(kkid->op_private & OPpLVAL_INTRO))
{
- /* Concat has problems if target is equal to right arg. */
- if (kid->op_type == OP_CONCAT) {
- if (kLISTOP->op_first->op_sibling->op_type == OP_PADSV
- && kLISTOP->op_first->op_sibling->op_targ == kkid->op_targ)
- return o;
- }
- else if (kid->op_type == OP_JOIN) {
- /* do_join has problems if the arguments coincide with target.
- In fact the second argument *can* safely coincide,
- but ignore=pessimize this rare occasion. */
- OP *arg = kLISTOP->op_first->op_sibling; /* Skip PUSHMARK */
-
- while (arg) {
- if (arg->op_type == OP_PADSV
- && arg->op_targ == kkid->op_targ)
- return o;
- arg = arg->op_sibling;
- }
- }
- else if (kid->op_type == OP_QUOTEMETA) {
- /* quotemeta has problems if the argument coincides with target. */
- if (kLISTOP->op_first->op_type == OP_PADSV
- && kLISTOP->op_first->op_targ == kkid->op_targ)
- return o;
- }
kid->op_targ = kkid->op_targ;
kkid->op_targ = 0;
/* Now we do not need PADSV and SASSIGN. */
return;
if (strEQ(GvNAME(gv), "a"))
reversed = 0;
- else if(strEQ(GvNAME(gv), "b"))
+ else if (strEQ(GvNAME(gv), "b"))
reversed = 1;
else
return;
case OP_UCFIRST:
case OP_LC:
case OP_LCFIRST:
- if ( o->op_next && o->op_next->op_type == OP_STRINGIFY
- && !(o->op_next->op_private & OPpTARGET_MY) )
- null(o->op_next);
- o->op_seq = PL_op_seqmax++;
- break;
case OP_CONCAT:
case OP_JOIN:
case OP_QUOTEMETA:
if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
if (o->op_next->op_private & OPpTARGET_MY) {
- if ((o->op_flags & OPf_STACKED) /* chained concats */
- || (o->op_type == OP_CONCAT
- /* Concat has problems if target is equal to right arg. */
- && (((LISTOP*)o)->op_first->op_sibling->op_type
- == OP_PADSV)
- && (((LISTOP*)o)->op_first->op_sibling->op_targ
- == o->op_next->op_targ)))
- {
+ if (o->op_flags & OPf_STACKED) /* chained concats */
goto ignore_optimization;
- }
else {
o->op_targ = o->op_next->op_targ;
o->op_next->op_targ = 0;
if (o->op_next->op_type == OP_RV2SV) {
if (!(o->op_next->op_private & OPpDEREF)) {
null(o->op_next);
- o->op_private |= o->op_next->op_private & OPpLVAL_INTRO;
+ o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO
+ | OPpOUR_INTRO);
o->op_next = o->op_next->op_next;
o->op_type = OP_GVSV;
o->op_ppaddr = PL_ppaddr[OP_GVSV];
GvAVn(gv);
}
}
- else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_UNSAFE)) {
+ else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
GV *gv = cGVOPo_gv;
if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX(GvCV(gv))) {
/* XXX could check prototype here instead of just carping */
SV *sv = sv_newmortal();
gv_efullname3(sv, gv, Nullch);
- Perl_warner(aTHX_ WARN_UNSAFE,
+ Perl_warner(aTHX_ WARN_PROTOTYPE,
"%s() called too early to check prototype",
SvPV_nolen(sv));
}
line_t oldline = CopLINE(PL_curcop);
CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next));
- Perl_warner(aTHX_ WARN_SYNTAX, "Statement unlikely to be reached");
- Perl_warner(aTHX_ WARN_SYNTAX, "(Maybe you meant system() when you said exec()?)\n");
+ Perl_warner(aTHX_ WARN_EXEC,
+ "Statement unlikely to be reached");
+ Perl_warner(aTHX_ WARN_EXEC,
+ "(Maybe you meant system() when you said exec()?)\n");
CopLINE_set(PL_curcop, oldline);
}
}
UNOP *rop;
SV *lexname;
GV **fields;
- SV **svp, **indsvp;
+ SV **svp, **indsvp, *sv;
I32 ind;
char *key;
STRLEN keylen;
+ o->op_seq = PL_op_seqmax++;
if ((o->op_private & (OPpLVAL_INTRO))
|| ((BINOP*)o)->op_last->op_type != OP_CONST)
break;
rop->op_ppaddr = PL_ppaddr[OP_RV2AV];
o->op_type = OP_AELEM;
o->op_ppaddr = PL_ppaddr[OP_AELEM];
+ sv = newSViv(ind);
+ if (SvREADONLY(*svp))
+ SvREADONLY_on(sv);
+ SvFLAGS(sv) |= (SvFLAGS(*svp)
+ & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY));
SvREFCNT_dec(*svp);
- *svp = newSViv(ind);
+ *svp = sv;
+ break;
+ }
+
+ case OP_HSLICE: {
+ UNOP *rop;
+ SV *lexname;
+ GV **fields;
+ SV **svp, **indsvp, *sv;
+ I32 ind;
+ char *key;
+ STRLEN keylen;
+ SVOP *first_key_op, *key_op;
+
+ o->op_seq = PL_op_seqmax++;
+ if ((o->op_private & (OPpLVAL_INTRO))
+ /* I bet there's always a pushmark... */
+ || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
+ /* hmmm, no optimization if list contains only one key. */
+ break;
+ rop = (UNOP*)((LISTOP*)o)->op_last;
+ if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
+ break;
+ lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
+ if (!SvOBJECT(lexname))
+ break;
+ fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+ if (!fields || !GvHV(*fields))
+ break;
+ /* Again guessing that the pushmark can be jumped over.... */
+ first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
+ ->op_first->op_sibling;
+ /* Check that the key list contains only constants. */
+ for (key_op = first_key_op; key_op;
+ key_op = (SVOP*)key_op->op_sibling)
+ if (key_op->op_type != OP_CONST)
+ break;
+ if (key_op)
+ break;
+ rop->op_type = OP_RV2AV;
+ rop->op_ppaddr = PL_ppaddr[OP_RV2AV];
+ o->op_type = OP_ASLICE;
+ o->op_ppaddr = PL_ppaddr[OP_ASLICE];
+ for (key_op = first_key_op; key_op;
+ key_op = (SVOP*)key_op->op_sibling) {
+ svp = cSVOPx_svp(key_op);
+ key = SvPV(*svp, keylen);
+ indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
+ if (!indsvp) {
+ Perl_croak(aTHX_ "No such pseudo-hash field \"%s\" "
+ "in variable %s of type %s",
+ key, SvPV(lexname, n_a), HvNAME(SvSTASH(lexname)));
+ }
+ ind = SvIV(*indsvp);
+ if (ind < 1)
+ Perl_croak(aTHX_ "Bad index while coercing array into hash");
+ sv = newSViv(ind);
+ if (SvREADONLY(*svp))
+ SvREADONLY_on(sv);
+ SvFLAGS(sv) |= (SvFLAGS(*svp)
+ & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY));
+ SvREFCNT_dec(*svp);
+ *svp = sv;
+ }
break;
}