/* op.c
*
- * Copyright (c) 1991-2000, Larry Wall
+ * Copyright (c) 1991-2001, 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 */
-#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
+#ifdef PL_OP_SLAB_ALLOC
#define SLAB_SIZE 8192
static char *PL_OpPtr = NULL;
static int PL_OpSpace = 0;
var = (type *) Slab_Alloc(m,c*sizeof(type)); \
} while (0)
-STATIC void *
+STATIC void *
S_Slab_Alloc(pTHX_ int m, size_t sz)
-{
+{
Newz(m,PL_OpPtr,SLAB_SIZE,char);
PL_OpSpace = SLAB_SIZE - sz;
return PL_OpPtr += PL_OpSpace;
}
-#else
+#else
#define NewOp(m, var, c, type) Newz(m, var, c, type)
#endif
/*
: CALL_FPTR(PL_check[type])(aTHX_ (OP*)o))
#define PAD_MAX 999999999
+#define RETURN_UNLIMITED_NUMBER (PERL_INT_MAX / 2)
STATIC char*
S_gv_ename(pTHX_ GV *gv)
SvPV_nolen(cSVOPo_sv)));
}
+STATIC U8*
+S_trlist_upgrade(pTHX_ U8** sp, U8** ep)
+{
+ U8 *s = *sp;
+ U8 *e = *ep;
+ U8 *d;
+
+ Newz(801, d, (e - s) * 2, U8);
+ *sp = d;
+
+ while (s < e) {
+ if (*s < 0x80 || *s == 0xff)
+ *d++ = *s++;
+ else {
+ U8 c = *s++;
+ *d++ = ((c >> 6) | 0xc0);
+ *d++ = ((c & 0x3f) | 0x80);
+ }
+ }
+ *ep = d;
+ return *sp;
+}
+
+
/* "register" allocation */
PADOFFSET
Perl_pad_allocmy(pTHX_ char *name)
{
- dTHR;
PADOFFSET off;
SV *sv;
- if (!(
- PL_in_my == KEY_our ||
- isALPHA(name[1]) ||
- (PL_hints & HINT_UTF8 && (name[1] & 0xc0) == 0xc0) ||
- name[1] == '_' && (int)strlen(name) > 2 ))
+ if (!(PL_in_my == KEY_our ||
+ isALPHA(name[1]) ||
+ (PL_hints & HINT_UTF8 && UTF8_IS_START(name[1])) ||
+ (name[1] == '_' && (int)strlen(name) > 2)))
{
if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) {
/* 1999-02-27 mjd@plover.com */
&& strEQ(name, SvPVX(sv)))
{
Perl_warner(aTHX_ WARN_MISC,
- "\"%s\" variable %s masks earlier declaration in same %s",
+ "\"%s\" variable %s masks earlier declaration in same %s",
(PL_in_my == KEY_our ? "our" : "my"),
name,
(SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
}
}
if (PL_in_my == KEY_our) {
- while (off >= 0 && off <= top) {
+ do {
if ((sv = svp[off])
&& sv != &PL_sv_undef
+ && (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
&& ((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");
+ "\t(Did you mean \"local\" instead of \"our\"?)\n");
break;
}
- --off;
- }
+ } while ( off-- > 0 );
}
}
off = pad_alloc(OP_PADSV, SVs_PADMY);
}
if (PL_in_my == KEY_our) {
(void)SvUPGRADE(sv, SVt_PVGV);
- GvSTASH(sv) = (HV*)SvREFCNT_inc(PL_curstash ? PL_curstash : PL_defstash);
+ GvSTASH(sv) = (HV*)SvREFCNT_inc(PL_curstash ? (SV*)PL_curstash : (SV*)PL_defstash);
SvFLAGS(sv) |= SVpad_OUR;
}
av_store(PL_comppad_name, off, sv);
S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv,
I32 cx_ix, I32 saweval, U32 flags)
{
- dTHR;
CV *cv;
I32 off;
SV *sv;
}
}
else if (!CvUNIQUE(PL_compcv)) {
- if (ckWARN(WARN_CLOSURE) && !SvFAKE(sv) && !CvUNIQUE(cv))
+ if (ckWARN(WARN_CLOSURE) && !SvFAKE(sv) && !CvUNIQUE(cv)
+ && !(SvFLAGS(sv) & SVpad_OUR))
+ {
Perl_warner(aTHX_ WARN_CLOSURE,
"Variable \"%s\" will not stay shared", name);
+ }
}
}
av_store(PL_comppad, newoff, SvREFCNT_inc(oldsv));
if (CxREALEVAL(cx))
saweval = i;
break;
+ case OP_DOFILE:
case OP_REQUIRE:
- /* require must have its own scope */
+ /* require/do must have their own scope */
return 0;
}
break;
PADOFFSET
Perl_pad_findmy(pTHX_ char *name)
{
- dTHR;
I32 off;
I32 pendoff = 0;
SV *sv;
void
Perl_pad_leavemy(pTHX_ I32 fill)
{
- dTHR;
I32 off;
SV **svp = AvARRAY(PL_comppad_name);
SV *sv;
PADOFFSET
Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype)
{
- dTHR;
SV *sv;
I32 retval;
(sv = names[PL_padix]) && sv != &PL_sv_undef)
continue;
sv = *av_fetch(PL_comppad, PL_padix, TRUE);
- if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)) && !IS_PADGV(sv))
+ if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)) &&
+ !IS_PADGV(sv) && !IS_PADCONST(sv))
break;
}
retval = PL_padix;
SV *
Perl_pad_sv(pTHX_ PADOFFSET po)
{
- dTHR;
#ifdef USE_THREADS
DEBUG_X(PerlIO_printf(Perl_debug_log,
"0x%"UVxf" Pad 0x%"UVxf" sv %"IVdf"\n",
void
Perl_pad_free(pTHX_ PADOFFSET po)
{
- dTHR;
if (!PL_curpad)
return;
if (AvARRAY(PL_comppad) != PL_curpad)
void
Perl_pad_swipe(pTHX_ PADOFFSET po)
{
- dTHR;
if (AvARRAY(PL_comppad) != PL_curpad)
Perl_croak(aTHX_ "panic: pad_swipe curpad");
if (!po)
Perl_pad_reset(pTHX)
{
#ifdef USE_BROKEN_PAD_RESET
- dTHR;
register I32 po;
if (AvARRAY(PL_comppad) != PL_curpad)
PADOFFSET
Perl_find_threadsv(pTHX_ const char *name)
{
- dTHR;
char *p;
PADOFFSET key;
SV **svp;
break;
case ';':
sv_setpv(sv, "\034");
- sv_magic(sv, 0, 0, name, 1);
+ sv_magic(sv, 0, 0, name, 1);
break;
case '&':
case '`':
/* case '!': */
default:
- sv_magic(sv, 0, 0, name, 1);
+ sv_magic(sv, 0, 0, name, 1);
}
DEBUG_S(PerlIO_printf(Perl_error_log,
"find_threadsv: new SV %p for $%s%c\n",
cSVOPo->op_sv = Nullsv;
#endif
break;
+ case OP_METHOD_NAMED:
case OP_CONST:
SvREFCNT_dec(cSVOPo->op_sv);
cSVOPo->op_sv = Nullsv;
{
Safefree(cop->cop_label);
#ifdef USE_ITHREADS
- Safefree(CopFILE(cop)); /* XXXXX share in a pvtable? */
- Safefree(CopSTASHPV(cop)); /* XXXXX share in a pvtable? */
+ Safefree(CopFILE(cop)); /* XXX share in a pvtable? */
+ Safefree(CopSTASHPV(cop)); /* XXX share in a pvtable? */
#else
/* NOTE: COP.cop_stash is not refcounted */
SvREFCNT_dec(CopFILEGV(cop));
#endif
if (! specialWARN(cop->cop_warnings))
SvREFCNT_dec(cop->cop_warnings);
+ if (! specialCopIO(cop->cop_io))
+ SvREFCNT_dec(cop->cop_io);
}
STATIC void
S_scalarboolean(pTHX_ OP *o)
{
if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST) {
- dTHR;
if (ckWARN(WARN_SYNTAX)) {
line_t oldline = CopLINE(PL_curcop);
case OP_LEAVETRY:
kid = cLISTOPo->op_first;
scalar(kid);
- while (kid = kid->op_sibling) {
+ while ((kid = kid->op_sibling)) {
if (kid->op_sibling)
scalarvoid(kid);
else
|| (o->op_type == OP_NULL && (o->op_targ == OP_NEXTSTATE
|| o->op_targ == OP_SETSTATE
|| o->op_targ == OP_DBSTATE)))
- {
- dTHR;
PL_curcop = (COP*)o; /* for warning below */
- }
/* assumes no premature commitment */
want = o->op_flags & OPf_WANT;
{
return scalar(o); /* As if inside SASSIGN */
}
-
+
o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_VOID;
switch (o->op_type) {
if (cSVOPo->op_private & OPpCONST_STRICT)
no_bareword_allowed(o);
else {
- dTHR;
if (ckWARN(WARN_VOID)) {
useless = "a constant";
if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0))
useless = 0;
else if (SvPOK(sv)) {
+ /* perl4's way of mixing documentation and code
+ (before the invention of POD) was based on a
+ trick to mix nroff and perl code. The trick was
+ built upon these three nroff macros being used in
+ void context. The pink camel has the details in
+ the script wrapman near page 319. */
if (strnEQ(SvPVX(sv), "di", 2) ||
strnEQ(SvPVX(sv), "ds", 2) ||
strnEQ(SvPVX(sv), "ig", 2))
case OP_DBSTATE:
case OP_ENTERTRY:
case OP_ENTER:
- case OP_SCALAR:
if (!(o->op_flags & OPf_KIDS))
break;
/* FALL THROUGH */
case OP_REQUIRE:
/* all requires must return a boolean value */
o->op_flags &= ~OPf_WANT;
+ /* FALL THROUGH */
+ case OP_SCALAR:
return scalar(o);
case OP_SPLIT:
if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) {
}
break;
}
- if (useless) {
- dTHR;
- if (ckWARN(WARN_VOID))
- Perl_warner(aTHX_ WARN_VOID, "Useless use of %s in void context", useless);
- }
+ if (useless && ckWARN(WARN_VOID))
+ Perl_warner(aTHX_ WARN_VOID, "Useless use of %s in void context", useless);
return o;
}
{
return o; /* As if inside SASSIGN */
}
-
+
o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_LIST;
switch (o->op_type) {
case OP_LEAVETRY:
kid = cLISTOPo->op_first;
list(kid);
- while (kid = kid->op_sibling) {
+ while ((kid = kid->op_sibling)) {
if (kid->op_sibling)
scalarvoid(kid);
else
o->op_type == OP_LEAVE ||
o->op_type == OP_LEAVETRY)
{
- dTHR;
for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) {
if (kid->op_sibling) {
scalarvoid(kid);
OP *
Perl_mod(pTHX_ OP *o, I32 type)
{
- dTHR;
OP *kid;
- SV *sv;
STRLEN n_a;
if (!o || PL_error_count)
{
return o;
}
-
+
switch (o->op_type) {
case OP_UNDEF:
PL_modcount++;
return o;
case OP_CONST:
+ if (o->op_private & (OPpCONST_BARE) &&
+ !(type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN)) {
+ SV *sv = ((SVOP*)o)->op_sv;
+ GV *gv;
+
+ /* Could be a filehandle */
+ if (gv = gv_fetchpv(SvPV_nolen(sv), FALSE, SVt_PVIO)) {
+ OP* gvio = newUNOP(OP_RV2GV, 0, newGVOP(OP_GV, 0, gv));
+ op_free(o);
+ o = gvio;
+ } else {
+ /* OK, it's a sub */
+ OP* enter;
+ gv = gv_fetchpv(SvPV_nolen(sv), TRUE, SVt_PVCV);
+
+ enter = newUNOP(OP_ENTERSUB,0,
+ newUNOP(OP_RV2CV, 0,
+ newGVOP(OP_GV, 0, gv)
+ ));
+ enter->op_private |= OPpLVAL_INTRO;
+ op_free(o);
+ o = enter;
+ }
+ break;
+ }
if (!(o->op_private & (OPpCONST_ARYBASE)))
goto nomod;
if (PL_eval_start && PL_eval_start->op_type == OP_CONST) {
}
else { /* lvalue subroutine call */
o->op_private |= OPpLVAL_INTRO;
+ PL_modcount = RETURN_UNLIMITED_NUMBER;
if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) {
/* Backward compatibility mode: */
o->op_private |= OPpENTERSUB_INARGS;
newop->op_private |= OPpLVAL_INTRO;
break;
}
-
+
if (kid->op_type != OP_RV2CV)
Perl_croak(aTHX_
"panic: unexpected lvalue entersub "
}
cv = GvCV(kGVOP_gv);
- if (!cv)
+ if (!cv)
goto restore_2cv;
if (CvLVALUE(cv))
break;
if (!type && cUNOPo->op_first->op_type != OP_GV)
Perl_croak(aTHX_ "Can't localize through a reference");
if (type == OP_REFGEN && o->op_flags & OPf_PARENS) {
- PL_modcount = 10000;
+ PL_modcount = RETURN_UNLIMITED_NUMBER;
return o; /* Treat \(@foo) like ordinary list. */
}
/* FALL THROUGH */
goto nomod;
ref(cUNOPo->op_first, o->op_type);
/* FALL THROUGH */
- case OP_AASSIGN:
case OP_ASLICE:
case OP_HSLICE:
+ if (type == OP_LEAVESUBLV)
+ o->op_private |= OPpMAYBE_LVSUB;
+ /* FALL THROUGH */
+ case OP_AASSIGN:
case OP_NEXTSTATE:
case OP_DBSTATE:
- case OP_REFGEN:
case OP_CHOMP:
- PL_modcount = 10000;
+ PL_modcount = RETURN_UNLIMITED_NUMBER;
break;
case OP_RV2SV:
if (!type && cUNOPo->op_first->op_type != OP_GV)
case OP_PADAV:
case OP_PADHV:
- PL_modcount = 10000;
+ PL_modcount = RETURN_UNLIMITED_NUMBER;
if (type == OP_REFGEN && o->op_flags & OPf_PARENS)
return o; /* Treat \(@foo) like ordinary list. */
if (scalar_mod_type(o, type))
goto nomod;
+ if (type == OP_LEAVESUBLV)
+ o->op_private |= OPpMAYBE_LVSUB;
/* FALL THROUGH */
case OP_PADSV:
PL_modcount++;
/* FALL THROUGH */
case OP_POS:
case OP_VEC:
+ if (type == OP_LEAVESUBLV)
+ o->op_private |= OPpMAYBE_LVSUB;
lvalue_func:
pad_free(o->op_targ);
o->op_targ = pad_alloc(o->op_type, SVs_PADMY);
if (type == OP_ENTERSUB &&
!(o->op_private & (OPpLVAL_INTRO | OPpDEREF)))
o->op_private |= OPpLVAL_DEFER;
+ if (type == OP_LEAVESUBLV)
+ o->op_private |= OPpMAYBE_LVSUB;
PL_modcount++;
break;
case OP_SCOPE:
case OP_LEAVE:
case OP_ENTER:
+ case OP_LINESEQ:
if (o->op_flags & OPf_KIDS)
mod(cLISTOPo->op_last, type);
break;
for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
mod(kid, type);
break;
+
+ case OP_RETURN:
+ if (type != OP_LEAVESUBLV)
+ goto nomod;
+ break; /* mod()ing was handled by ck_return() */
}
- o->op_flags |= OPf_MOD;
+ if (type != OP_LEAVESUBLV)
+ o->op_flags |= OPf_MOD;
if (type == OP_AASSIGN || type == OP_SASSIGN)
o->op_flags |= OPf_SPECIAL|OPf_REF;
o->op_flags &= ~OPf_SPECIAL;
PL_hints |= HINT_BLOCK_SCOPE;
}
- else if (type != OP_GREPSTART && type != OP_ENTERSUB)
+ else if (type != OP_GREPSTART && type != OP_ENTERSUB
+ && type != OP_LEAVESUBLV)
o->op_flags |= OPf_REF;
return o;
}
o->op_flags |= OPf_MOD;
}
break;
-
+
case OP_THREADSV:
o->op_flags |= OPf_MOD; /* XXX ??? */
break;
STATIC void
S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs)
{
- OP *modname; /* for 'use' */
SV *stashsv;
/* fake up C<use attributes $pkg,$rv,@attrs> */
stashsv = newSVpv(HvNAME(stash), 0);
else
stashsv = &PL_sv_no;
+
#define ATTRSMODULE "attributes"
- modname = newSVOP(OP_CONST, 0,
- newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1));
- modname->op_private |= OPpCONST_BARE;
- /* that flag is required to make 'use' work right */
- utilize(1, start_subparse(FALSE, 0),
- Nullop, /* version */
- modname,
- prepend_elem(OP_LIST,
- newSVOP(OP_CONST, 0, stashsv),
- prepend_elem(OP_LIST,
- newSVOP(OP_CONST, 0, newRV(target)),
- dup_attrlist(attrs))));
+
+ Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
+ newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
+ Nullsv,
+ prepend_elem(OP_LIST,
+ newSVOP(OP_CONST, 0, stashsv),
+ prepend_elem(OP_LIST,
+ newSVOP(OP_CONST, 0,
+ newRV(target)),
+ dup_attrlist(attrs))));
LEAVE;
}
+void
+Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv,
+ char *attrstr, STRLEN len)
+{
+ OP *attrs = Nullop;
+
+ if (!len) {
+ len = strlen(attrstr);
+ }
+
+ while (len) {
+ for (; isSPACE(*attrstr) && len; --len, ++attrstr) ;
+ if (len) {
+ char *sstr = attrstr;
+ for (; !isSPACE(*attrstr) && len; --len, ++attrstr) ;
+ attrs = append_elem(OP_LIST, attrs,
+ newSVOP(OP_CONST, 0,
+ newSVpvn(sstr, attrstr-sstr)));
+ }
+ }
+
+ Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
+ newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
+ Nullsv, prepend_elem(OP_LIST,
+ newSVOP(OP_CONST, 0, newSVpv(stashpv,0)),
+ prepend_elem(OP_LIST,
+ newSVOP(OP_CONST, 0,
+ newRV((SV*)cv)),
+ attrs)));
+}
+
STATIC OP *
S_my_kid(pTHX_ OP *o, OP *attrs)
{
OP *
Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
{
- dTHR;
OP *o;
if (ckWARN(WARN_MISC) &&
left->op_type == OP_PADAV)
? "@array" : "%hash");
Perl_warner(aTHX_ WARN_MISC,
- "Applying %s to %s will act on scalar(%s)",
+ "Applying %s to %s will act on scalar(%s)",
desc, sample, sample);
}
- if (right->op_type == OP_MATCH ||
+ if (!(right->op_flags & OPf_STACKED) &&
+ (right->op_type == OP_MATCH ||
right->op_type == OP_SUBST ||
- right->op_type == OP_TRANS) {
+ right->op_type == OP_TRANS)) {
right->op_flags |= OPf_STACKED;
- if (right->op_type != OP_MATCH)
+ if (right->op_type != OP_MATCH &&
+ ! (right->op_type == OP_TRANS &&
+ right->op_private & OPpTRANS_IDENTICAL))
left = mod(left, right->op_type);
if (right->op_type == OP_TRANS)
o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right);
int
Perl_block_start(pTHX_ int full)
{
- dTHR;
int retval = PL_savestack_ix;
SAVEI32(PL_comppad_name_floor);
PL_pad_reset_pending = FALSE;
SAVEHINTS();
PL_hints &= ~HINT_BLOCK_SCOPE;
- SAVESPTR(PL_compiling.cop_warnings);
+ SAVESPTR(PL_compiling.cop_warnings);
if (! specialWARN(PL_compiling.cop_warnings)) {
PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
SAVEFREESV(PL_compiling.cop_warnings) ;
}
+ SAVESPTR(PL_compiling.cop_io);
+ if (! specialCopIO(PL_compiling.cop_io)) {
+ PL_compiling.cop_io = newSVsv(PL_compiling.cop_io) ;
+ SAVEFREESV(PL_compiling.cop_io) ;
+ }
return retval;
}
OP*
Perl_block_end(pTHX_ I32 floor, OP *seq)
{
- dTHR;
int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
OP* retval = scalarseq(seq);
LEAVE_SCOPE(floor);
void
Perl_newPROG(pTHX_ OP *o)
{
- dTHR;
if (PL_in_eval) {
if (PL_eval_root)
return;
if (o->op_flags & OPf_PARENS)
list(o);
else {
- dTHR;
if (ckWARN(WARN_PARENTHESIS) && PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',') {
char *s;
- for (s = PL_bufptr; *s && (isALNUM(*s) || (*s & 0x80) || strchr("@$%, ",*s)); s++) ;
+ for (s = PL_bufptr; *s && (isALNUM(*s) || UTF8_IS_CONTINUED(*s) || strchr("@$%, ",*s)); s++) ;
if (*s == ';' || *s == '=')
Perl_warner(aTHX_ WARN_PARENTHESIS,
"Parentheses missing around \"%s\" list",
OP *
Perl_fold_constants(pTHX_ register OP *o)
{
- dTHR;
register OP *curop;
I32 type = o->op_type;
SV *sv;
if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK &&
type != OP_NEGATE)
{
- IV iv = SvIV(sv);
- if ((NV)iv == SvNV(sv)) {
- SvREFCNT_dec(sv);
- sv = newSViv(iv);
- }
- else
- SvIOK_off(sv); /* undo SvIV() damage */
+#ifdef PERL_PRESERVE_IVUV
+ /* Only bother to attempt to fold to IV if
+ most operators will benefit */
+ SvIV_please(sv);
+#endif
}
return newSVOP(OP_CONST, 0, sv);
}
OP *
Perl_gen_constant_list(pTHX_ register OP *o)
{
- dTHR;
register OP *curop;
I32 oldtmps_floor = PL_tmps_floor;
if (o->op_type != type)
return o;
- if (cLISTOPo->op_children < 7) {
- /* XXX do we really need to do this if we're done appending?? */
- for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
- last = kid;
- cLISTOPo->op_last = last; /* in case check substituted last arg */
- }
-
return fold_constants(o);
}
if (!last)
return first;
- if (first->op_type != type || type==OP_LIST && first->op_flags & OPf_PARENS)
- return newLISTOP(type, 0, first, last);
+ if (first->op_type != type
+ || (type == OP_LIST && (first->op_flags & OPf_PARENS)))
+ {
+ return newLISTOP(type, 0, first, last);
+ }
if (first->op_flags & OPf_KIDS)
((LISTOP*)first)->op_last->op_sibling = last;
((LISTOP*)first)->op_first = last;
}
((LISTOP*)first)->op_last = last;
- ((LISTOP*)first)->op_children++;
return first;
}
first->op_last->op_sibling = last->op_first;
first->op_last = last->op_last;
- first->op_children += last->op_children;
- if (first->op_children)
- first->op_flags |= OPf_KIDS;
-
+ first->op_flags |= (last->op_flags & OPf_KIDS);
+
#ifdef PL_OP_SLAB_ALLOC
#else
- Safefree(last);
+ Safefree(last);
#endif
return (OP*)first;
}
if (type == OP_LIST) { /* already a PUSHMARK there */
first->op_sibling = ((LISTOP*)last)->op_first->op_sibling;
((LISTOP*)last)->op_first->op_sibling = first;
+ if (!(first->op_flags & OPf_PARENS))
+ last->op_flags &= ~OPf_PARENS;
}
else {
if (!(last->op_flags & OPf_KIDS)) {
first->op_sibling = ((LISTOP*)last)->op_first;
((LISTOP*)last)->op_first = first;
}
- ((LISTOP*)last)->op_children++;
+ last->op_flags |= OPf_KIDS;
return last;
}
listop->op_type = type;
listop->op_ppaddr = PL_ppaddr[type];
- listop->op_children = (first != 0) + (last != 0);
+ if (first || last)
+ flags |= OPf_KIDS;
listop->op_flags = flags;
if (!last && first)
if (!last)
listop->op_last = pushop;
}
- else if (listop->op_children)
- listop->op_flags |= OPf_KIDS;
return (OP*)listop;
}
SV *rstr = ((SVOP*)repl)->op_sv;
STRLEN tlen;
STRLEN rlen;
- register U8 *t = (U8*)SvPV(tstr, tlen);
- register U8 *r = (U8*)SvPV(rstr, rlen);
+ U8 *t = (U8*)SvPV(tstr, tlen);
+ U8 *r = (U8*)SvPV(rstr, rlen);
register I32 i;
register I32 j;
I32 del;
I32 complement;
I32 squash;
+ I32 grows = 0;
register short *tbl;
complement = o->op_private & OPpTRANS_COMPLEMENT;
del = o->op_private & OPpTRANS_DELETE;
squash = o->op_private & OPpTRANS_SQUASH;
+ if (SvUTF8(tstr))
+ o->op_private |= OPpTRANS_FROM_UTF;
+
+ if (SvUTF8(rstr))
+ o->op_private |= OPpTRANS_TO_UTF;
+
if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) {
SV* listsv = newSVpvn("# comment\n",10);
SV* transv = 0;
U8* tend = t + tlen;
U8* rend = r + rlen;
- I32 ulen;
+ STRLEN ulen;
U32 tfirst = 1;
U32 tlast = 0;
I32 tdiff;
I32 none = 0;
U32 max = 0;
I32 bits;
- I32 grows = 0;
I32 havefinal = 0;
U32 final;
- HV *hv;
I32 from_utf = o->op_private & OPpTRANS_FROM_UTF;
I32 to_utf = o->op_private & OPpTRANS_TO_UTF;
+ U8* tsave = from_utf ? NULL : trlist_upgrade(&t, &tend);
+ U8* rsave = to_utf ? NULL : trlist_upgrade(&r, &rend);
if (complement) {
- U8 tmpbuf[UTF8_MAXLEN];
+ U8 tmpbuf[UTF8_MAXLEN+1];
U8** cp;
+ I32* cl;
UV nextmin = 0;
New(1109, cp, tlen, U8*);
i = 0;
qsort(cp, i, sizeof(U8*), utf8compare);
for (j = 0; j < i; j++) {
U8 *s = cp[j];
- UV val = utf8_to_uv(s, &ulen);
+ I32 cur = j < i ? cp[j+1] - s : tend - s;
+ UV val = utf8_to_uv(s, cur, &ulen, 0);
s += ulen;
diff = val - nextmin;
if (diff > 0) {
}
}
if (*s == 0xff)
- val = utf8_to_uv(s+1, &ulen);
+ val = utf8_to_uv(s+1, cur - 1, &ulen, 0);
if (val >= nextmin)
nextmin = val + 1;
}
r = t; rlen = tlen; rend = tend;
}
if (!squash) {
- if (to_utf && from_utf) { /* only counting characters */
- if (t == r || (tlen == rlen && memEQ(t, r, tlen)))
- o->op_private |= OPpTRANS_IDENTICAL;
- }
- else { /* straight latin-1 translation */
- if (tlen == 4 && memEQ(t, "\0\377\303\277", 4) &&
- rlen == 4 && memEQ(r, "\0\377\303\277", 4))
+ if (t == r ||
+ (tlen == rlen && memEQ((char *)t, (char *)r, tlen)))
+ {
o->op_private |= OPpTRANS_IDENTICAL;
- }
+ }
}
while (t < tend || tfirst <= tlast) {
/* see if we need more "t" chars */
if (tfirst > tlast) {
- tfirst = (I32)utf8_to_uv(t, &ulen);
+ tfirst = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
t += ulen;
if (t < tend && *t == 0xff) { /* illegal utf8 val indicates range */
- tlast = (I32)utf8_to_uv(++t, &ulen);
+ t++;
+ tlast = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
t += ulen;
}
else
/* now see if we need more "r" chars */
if (rfirst > rlast) {
if (r < rend) {
- rfirst = (I32)utf8_to_uv(r, &ulen);
+ rfirst = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
r += ulen;
if (r < rend && *r == 0xff) { /* illegal utf8 val indicates range */
- rlast = (I32)utf8_to_uv(++r, &ulen);
+ r++;
+ rlast = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
r += ulen;
}
else
if (rfirst + diff > max)
max = rfirst + diff;
rfirst += diff + 1;
- if (!grows) {
- if (rfirst <= 0x80)
- ;
- else if (rfirst <= 0x800)
- grows |= (tfirst < 0x80);
- else if (rfirst <= 0x10000)
- grows |= (tfirst < 0x800);
- else if (rfirst <= 0x200000)
- grows |= (tfirst < 0x10000);
- else if (rfirst <= 0x4000000)
- grows |= (tfirst < 0x200000);
- else if (rfirst <= 0x80000000)
- grows |= (tfirst < 0x4000000);
- }
+ if (!grows)
+ grows = (UNISKIP(tfirst) < UNISKIP(rfirst));
}
tfirst += diff + 1;
}
SvREFCNT_dec(transv);
if (!del && havefinal)
- (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5, newSViv((IV)final), 0);
+ (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
+ newSVuv((UV)final), 0);
- if (grows && to_utf)
+ if (grows)
o->op_private |= OPpTRANS_GROWS;
+ if (tsave)
+ Safefree(tsave);
+ if (rsave)
+ Safefree(rsave);
+
op_free(expr);
op_free(repl);
return o;
else
tbl[i] = i;
}
- else
+ else {
+ if (i < 128 && r[j] >= 128)
+ grows = 1;
tbl[i] = r[j++];
+ }
}
}
}
}
--j;
}
- if (tbl[t[i]] == -1)
+ if (tbl[t[i]] == -1) {
+ if (t[i] < 128 && r[j] >= 128)
+ grows = 1;
tbl[t[i]] = r[j];
+ }
}
}
+ if (grows)
+ o->op_private |= OPpTRANS_GROWS;
op_free(expr);
op_free(repl);
OP *
Perl_newPMOP(pTHX_ I32 type, I32 flags)
{
- dTHR;
PMOP *pmop;
NewOp(1101, pmop, 1, PMOP);
OP *
Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
{
- dTHR;
PMOP *pm;
LOGOP *rcop;
I32 repl_has_vars = 0;
p = SvPV(pat, plen);
pm->op_pmflags |= PMf_SKIPWHITE;
}
- if ((PL_hints & HINT_UTF8) || (SvUTF8(pat) && !(PL_hints & HINT_BYTE)))
+ if ((PL_hints & HINT_UTF8) || DO_UTF8(pat))
pm->op_pmdynflags |= PMdf_UTF8;
pm->op_pmregexp = CALLREGCOMP(aTHX_ p, p + plen, pm);
if (strEQ("\\s+", pm->op_pmregexp->precomp))
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)
+ expr = newUNOP((!(PL_hints & HINT_RE_EVAL)
? OP_REGCRESET
: OP_REGCMAYBE),0,expr);
rcop->op_type = OP_REGCOMP;
rcop->op_ppaddr = PL_ppaddr[OP_REGCOMP];
rcop->op_first = scalar(expr);
- rcop->op_flags |= ((PL_hints & HINT_RE_EVAL)
+ rcop->op_flags |= ((PL_hints & HINT_RE_EVAL)
? (OPf_SPECIAL | OPf_KIDS)
: OPf_KIDS);
rcop->op_private = 1;
}
}
if (curop == repl
- && !(repl_has_vars
- && (!pm->op_pmregexp
+ && !(repl_has_vars
+ && (!pm->op_pmregexp
|| pm->op_pmregexp->reganch & ROPT_EVAL_SEEN))) {
pm->op_pmflags |= PMf_CONST; /* const for long enough */
pm->op_pmpermflags |= PMf_CONST; /* const for long enough */
OP *
Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv)
{
- dTHR;
#ifdef USE_ITHREADS
GvIN_PAD_on(gv);
return newPADOP(type, flags, SvREFCNT_inc(gv));
void
Perl_package(pTHX_ OP *o)
{
- dTHR;
SV *sv;
save_hptr(&PL_curstash);
Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg)
{
OP *pack;
- OP *meth;
OP *rqop;
OP *imop;
OP *veop;
/* Fake up a method call to VERSION */
meth = newSVpvn("VERSION",7);
sv_upgrade(meth, SVt_PVIV);
- SvIOK_on(meth);
+ (void)SvIOK_on(meth);
PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
append_elem(OP_LIST,
/* Fake up a method call to import/unimport */
meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);;
sv_upgrade(meth, SVt_PVIV);
- SvIOK_on(meth);
+ (void)SvIOK_on(meth);
PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL,
append_elem(OP_LIST,
PL_expect = XSTATE;
}
+void
+Perl_load_module(pTHX_ U32 flags, SV *name, SV *ver, ...)
+{
+ va_list args;
+ va_start(args, ver);
+ vload_module(flags, name, ver, &args);
+ va_end(args);
+}
+
+#ifdef PERL_IMPLICIT_CONTEXT
+void
+Perl_load_module_nocontext(U32 flags, SV *name, SV *ver, ...)
+{
+ dTHX;
+ va_list args;
+ va_start(args, ver);
+ vload_module(flags, name, ver, &args);
+ va_end(args);
+}
+#endif
+
+void
+Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
+{
+ OP *modname, *veop, *imop;
+
+ modname = newSVOP(OP_CONST, 0, name);
+ modname->op_private |= OPpCONST_BARE;
+ if (ver) {
+ veop = newSVOP(OP_CONST, 0, ver);
+ }
+ else
+ veop = Nullop;
+ if (flags & PERL_LOADMOD_NOIMPORT) {
+ imop = sawparens(newNULLLIST());
+ }
+ else if (flags & PERL_LOADMOD_IMPORT_OPS) {
+ imop = va_arg(*args, OP*);
+ }
+ else {
+ SV *sv;
+ imop = Nullop;
+ sv = va_arg(*args, SV*);
+ while (sv) {
+ imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv));
+ sv = va_arg(*args, SV*);
+ }
+ }
+ {
+ line_t ocopline = PL_copline;
+ int oexpect = PL_expect;
+
+ utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
+ veop, modname, imop);
+ PL_expect = oexpect;
+ PL_copline = ocopline;
+ }
+}
+
OP *
Perl_dofile(pTHX_ OP *term)
{
}
if (list_assignment(left)) {
- dTHR;
+ OP *curop;
+
PL_modcount = 0;
PL_eval_start = right; /* Grandfathering $[ assignment here. Bletch.*/
left = mod(left, OP_AASSIGN);
op_free(right);
return Nullop;
}
- o = newBINOP(OP_AASSIGN, flags,
- list(force_list(right)),
- list(force_list(left)) );
+ curop = list(force_list(left));
+ o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop);
o->op_private = 0 | (flags >> 8);
+ for (curop = ((LISTOP*)curop)->op_first;
+ curop; curop = curop->op_sibling)
+ {
+ if (curop->op_type == OP_RV2HV &&
+ ((UNOP*)curop)->op_first->op_type != OP_GV) {
+ o->op_private |= OPpASSIGN_HASH;
+ break;
+ }
+ }
if (!(left->op_private & OPpLVAL_INTRO)) {
- OP *curop;
OP *lastop = o;
PL_generation++;
for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
}
else if (curop->op_type == OP_PUSHRE) {
if (((PMOP*)curop)->op_pmreplroot) {
+#ifdef USE_ITHREADS
+ GV *gv = (GV*)PL_curpad[(PADOFFSET)((PMOP*)curop)->op_pmreplroot];
+#else
GV *gv = (GV*)((PMOP*)curop)->op_pmreplroot;
+#endif
if (gv == PL_defgv || SvCUR(gv) == PL_generation)
break;
SvCUR(gv) = PL_generation;
lastop = curop;
}
if (curop != o)
- o->op_private = OPpASSIGN_COMMON;
+ o->op_private |= OPpASSIGN_COMMON;
}
if (right && right->op_type == OP_SPLIT) {
OP* tmpop;
}
}
else {
- if (PL_modcount < 10000 &&
+ if (PL_modcount < RETURN_UNLIMITED_NUMBER &&
((LISTOP*)right)->op_last->op_type == OP_CONST)
{
SV *sv = ((SVOP*)((LISTOP*)right)->op_last)->op_sv;
OP *
Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
{
- dTHR;
U32 seq = intro_my();
register COP *cop;
cop->cop_arybase = PL_curcop->cop_arybase;
if (specialWARN(PL_curcop->cop_warnings))
cop->cop_warnings = PL_curcop->cop_warnings ;
- else
+ else
cop->cop_warnings = newSVsv(PL_curcop->cop_warnings) ;
+ if (specialCopIO(PL_curcop->cop_io))
+ cop->cop_io = PL_curcop->cop_io;
+ else
+ cop->cop_io = newSVsv(PL_curcop->cop_io) ;
if (PL_copline == NOLINE)
PL_copline = NOLINE;
}
#ifdef USE_ITHREADS
- CopFILE_set(cop, CopFILE(PL_curcop)); /* XXXXX share in a pvtable? */
+ CopFILE_set(cop, CopFILE(PL_curcop)); /* XXX share in a pvtable? */
#else
- CopFILEGV_set(cop, (GV*)SvREFCNT_inc(CopFILEGV(PL_curcop)));
+ CopFILEGV_set(cop, CopFILEGV(PL_curcop));
#endif
CopSTASH_set(cop, PL_curstash);
STATIC OP *
S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
{
- dTHR;
LOGOP *logop;
OP *o;
OP *first = *firstp;
}
if (first->op_type == OP_CONST) {
if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE))
- Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional");
+ Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional");
if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
op_free(first);
*firstp = Nullop;
case OP_NULL:
if (k2 && k2->op_type == OP_READLINE
&& (k2->op_flags & OPf_STACKED)
- && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
+ && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
{
warnop = k2->op_type;
}
OP *
Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop)
{
- dTHR;
LOGOP *logop;
OP *start;
OP *o;
OP *
Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right)
{
- dTHR;
LOGOP *range;
OP *flip;
OP *flop;
OP *
Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block)
{
- dTHR;
OP* listop;
OP* o;
int once = block && block->op_flags & OPf_SPECIAL &&
OP *k1 = ((UNOP*)expr)->op_first;
OP *k2 = (k1) ? k1->op_sibling : NULL;
switch (expr->op_type) {
- case OP_NULL:
+ case OP_NULL:
if (k2 && k2->op_type == OP_READLINE
&& (k2->op_flags & OPf_STACKED)
- && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
+ && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
expr = newUNOP(OP_DEFINED, 0, expr);
- break;
+ break;
case OP_SASSIGN:
if (k1->op_type == OP_READDIR
OP *
Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *block, OP *cont)
{
- dTHR;
OP *redo;
OP *next = 0;
OP *listop;
OP *o;
OP *condop;
+ U8 loopflags = 0;
if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
|| (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
OP *k1 = ((UNOP*)expr)->op_first;
OP *k2 = (k1) ? k1->op_sibling : NULL;
switch (expr->op_type) {
- case OP_NULL:
+ case OP_NULL:
if (k2 && k2->op_type == OP_READLINE
&& (k2->op_flags & OPf_STACKED)
- && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
+ && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
expr = newUNOP(OP_DEFINED, 0, expr);
- break;
+ break;
case OP_SASSIGN:
if (k1->op_type == OP_READDIR
block = scope(block);
}
- if (cont)
+ if (cont) {
next = LINKLIST(cont);
+ }
if (expr) {
- cont = append_elem(OP_LINESEQ, cont, newOP(OP_UNSTACK, 0));
+ OP *unstack = newOP(OP_UNSTACK, 0);
+ if (!next)
+ next = unstack;
+ cont = append_elem(OP_LINESEQ, cont, unstack);
if ((line_t)whileline != NOLINE) {
PL_copline = whileline;
cont = append_elem(OP_LINESEQ, cont,
if (listop)
((LISTOP*)listop)->op_last->op_next = condop =
(o == listop ? redo : LINKLIST(o));
- if (!next)
- next = condop;
}
else
o = listop;
loop->op_redoop = redo;
loop->op_lastop = o;
+ o->op_private |= loopflags;
if (next)
loop->op_nextop = next;
Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont)
{
LOOP *loop;
- LOOP *tmp;
OP *wop;
int padoff = 0;
I32 iterflags = 0;
append_elem(OP_LIST, expr, scalar(sv))));
assert(!loop->op_next);
#ifdef PL_OP_SLAB_ALLOC
- NewOp(1234,tmp,1,LOOP);
- Copy(loop,tmp,1,LOOP);
- loop = tmp;
+ {
+ LOOP *tmp;
+ NewOp(1234,tmp,1,LOOP);
+ Copy(loop,tmp,1,LOOP);
+ loop = tmp;
+ }
#else
Renew(loop, 1, LOOP);
-#endif
+#endif
loop->op_targ = padoff;
wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont);
PL_copline = forline;
OP*
Perl_newLOOPEX(pTHX_ I32 type, OP *label)
{
- dTHR;
OP *o;
STRLEN n_a;
void
Perl_cv_undef(pTHX_ CV *cv)
{
- dTHR;
#ifdef USE_THREADS
if (CvMUTEXP(cv)) {
MUTEX_DESTROY(CvMUTEXP(cv));
CvGV(cv) = Nullgv;
SvREFCNT_dec(CvOUTSIDE(cv));
CvOUTSIDE(cv) = Nullcv;
+ if (CvCONST(cv)) {
+ SvREFCNT_dec((SV*)CvXSUBANY(cv).any_ptr);
+ CvCONST_off(cv);
+ }
if (CvPADLIST(cv)) {
/* may be during global destruction */
if (SvREFCNT(CvPADLIST(cv))) {
STATIC CV *
S_cv_clone2(pTHX_ CV *proto, CV *outside)
{
- dTHR;
AV* av;
I32 ix;
AV* protopadlist = CvPADLIST(proto);
cv = PL_compcv = (CV*)NEWSV(1104,0);
sv_upgrade((SV *)cv, SvTYPE(proto));
+ CvFLAGS(cv) = CvFLAGS(proto) & ~CVf_CLONE;
CvCLONED_on(cv);
- if (CvANON(proto))
- CvANON_on(cv);
#ifdef USE_THREADS
New(666, CvMUTEXP(cv), 1, perl_mutex);
#endif
LEAVE;
+
+ if (CvCONST(cv)) {
+ SV* const_sv = op_const_sv(CvSTART(cv), cv);
+ assert(const_sv);
+ /* constant sub () { $x } closing over $x - see lib/constant.pm */
+ SvREFCNT_dec(cv);
+ cv = newCONSTSUB(CvSTASH(proto), 0, const_sv);
+ }
+
return cv;
}
void
Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
{
- dTHR;
-
if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_PROTOTYPE)) {
SV* msg = sv_newmortal();
SV* name = Nullsv;
}
}
+static void const_sv_xsub(pTHXo_ CV* cv);
+
+/*
+=for apidoc cv_const_sv
+
+If C<cv> is a constant sub eligible for inlining. returns the constant
+value returned by the sub. Otherwise, returns NULL.
+
+Constant subs can be created with C<newCONSTSUB> or as described in
+L<perlsub/"Constant Functions">.
+
+=cut
+*/
SV *
Perl_cv_const_sv(pTHX_ CV *cv)
{
- if (!cv || !SvPOK(cv) || SvCUR(cv))
+ if (!cv || !CvCONST(cv))
return Nullsv;
- return op_const_sv(CvSTART(cv), cv);
+ return (SV*)CvXSUBANY(cv).any_ptr;
}
SV *
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) {
OPCODE type = o->op_type;
- if (sv && o->op_next == o)
+ if (sv && o->op_next == o)
return sv;
- if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK)
- continue;
+ if (o->op_next != o) {
+ if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK)
+ continue;
+ if (type == OP_DBSTATE)
+ continue;
+ }
if (type == OP_LEAVESUB || type == OP_RETURN)
break;
if (sv)
else if ((type == OP_PADSV || type == OP_CONST) && cv) {
AV* padav = (AV*)(AvARRAY(CvPADLIST(cv))[1]);
sv = padav ? AvARRAY(padav)[o->op_targ] : Nullsv;
- if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1))
+ if (!sv)
+ return Nullsv;
+ if (CvCONST(cv)) {
+ /* We get here only from cv_clone2() while creating a closure.
+ Copy the const value here instead of in cv_clone2 so that
+ SvREADONLY_on doesn't lead to problems when leaving
+ scope.
+ */
+ sv = newSVsv(sv);
+ }
+ if (!SvREADONLY(sv) && SvREFCNT(sv) > 1)
return Nullsv;
}
else
CV *
Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
{
- dTHR;
STRLEN n_a;
char *name;
char *aname;
char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch;
register CV *cv=0;
I32 ix;
+ SV *const_sv;
name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) {
SvREFCNT_dec(PL_compcv);
cv = PL_compcv = NULL;
PL_sub_generation++;
- goto noblock;
+ goto done;
}
- if (!name || GvCVGEN(gv))
- cv = Nullcv;
- else if (cv = GvCV(gv)) {
- cv_ckproto(cv, gv, ps);
+ cv = (!name || GvCVGEN(gv)) ? Nullcv : GvCV(gv);
+
+ if (!block || !ps || *ps || attrs)
+ const_sv = Nullsv;
+ else
+ const_sv = op_const_sv(block, Nullcv);
+
+ if (cv) {
+ bool exists = CvROOT(cv) || CvXSUB(cv);
+ /* if the subroutine doesn't exist and wasn't pre-declared
+ * with a prototype, assume it will be AUTOLOADed,
+ * skipping the prototype check
+ */
+ if (exists || SvPOK(cv))
+ cv_ckproto(cv, gv, ps);
/* already defined (or promised)? */
- if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
- SV* const_sv;
- bool const_changed = TRUE;
+ if (exists || GvASSUMECV(gv)) {
if (!block && !attrs) {
/* just a "sub foo;" when &foo is already defined */
SAVEFREESV(PL_compcv);
/* ahem, death to those who redefine active sort subs */
if (PL_curstackinfo->si_type == PERLSI_SORT && PL_sortcop == CvSTART(cv))
Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name);
- if (!block)
- goto withattrs;
- 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))
- {
- line_t oldline = CopLINE(PL_curcop);
- CopLINE_set(PL_curcop, PL_copline);
- Perl_warner(aTHX_ WARN_REDEFINE,
- const_sv ? "Constant subroutine %s redefined"
- : "Subroutine %s redefined", name);
- CopLINE_set(PL_curcop, oldline);
+ if (block) {
+ if (ckWARN(WARN_REDEFINE)
+ || (CvCONST(cv)
+ && (!const_sv || sv_cmp(cv_const_sv(cv), const_sv))))
+ {
+ line_t oldline = CopLINE(PL_curcop);
+ CopLINE_set(PL_curcop, PL_copline);
+ Perl_warner(aTHX_ WARN_REDEFINE,
+ CvCONST(cv) ? "Constant subroutine %s redefined"
+ : "Subroutine %s redefined", name);
+ CopLINE_set(PL_curcop, oldline);
+ }
+ SvREFCNT_dec(cv);
+ cv = Nullcv;
}
- SvREFCNT_dec(cv);
- cv = Nullcv;
}
}
- withattrs:
+ if (const_sv) {
+ SvREFCNT_inc(const_sv);
+ if (cv) {
+ assert(!CvROOT(cv) && !CvCONST(cv));
+ sv_setpv((SV*)cv, ""); /* prototype is "" */
+ CvXSUBANY(cv).any_ptr = const_sv;
+ CvXSUB(cv) = const_sv_xsub;
+ CvCONST_on(cv);
+ }
+ else {
+ GvCV(gv) = Nullcv;
+ cv = newCONSTSUB(NULL, name, const_sv);
+ }
+ op_free(block);
+ SvREFCNT_dec(PL_compcv);
+ PL_compcv = NULL;
+ PL_sub_generation++;
+ goto done;
+ }
if (attrs) {
HV *stash;
SV *rcv;
}
}
}
- if (!block) {
- noblock:
- PL_copline = NOLINE;
- LEAVE_SCOPE(floor);
- return cv;
- }
+ if (!block)
+ goto done;
if (AvFILLp(PL_comppad_name) < AvFILLp(PL_comppad))
av_store(PL_comppad_name, AvFILLp(PL_comppad), Nullsv);
if (CvLVALUE(cv)) {
- CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0, scalarseq(block));
+ CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0,
+ mod(scalarseq(block), OP_LEAVESUBLV));
}
else {
CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block));
PL_curpad[ix] = Nullsv;
}
}
+ assert(!CvCONST(cv));
+ if (ps && !*ps && op_const_sv(block, cv))
+ CvCONST_on(cv);
}
else {
AV *av = newAV(); /* Will be @_ */
GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV);
CV *pcv;
HV *hv;
- char *t;
Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld",
CopFILE(PL_curcop),
if (!PL_beginav)
PL_beginav = newAV();
DEBUG_x( dump_sub(gv) );
- av_push(PL_beginav, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_push(PL_beginav, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
call_list(oldscope, PL_beginav);
PL_curcop = &PL_compiling;
PL_endav = newAV();
DEBUG_x( dump_sub(gv) );
av_unshift(PL_endav, 1);
- av_store(PL_endav, 0, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_store(PL_endav, 0, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
else if (strEQ(s, "CHECK") && !PL_error_count) {
if (!PL_checkav)
PL_checkav = newAV();
DEBUG_x( dump_sub(gv) );
+ if (PL_main_start && ckWARN(WARN_VOID))
+ Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block");
av_unshift(PL_checkav, 1);
- av_store(PL_checkav, 0, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_store(PL_checkav, 0, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
else if (strEQ(s, "INIT") && !PL_error_count) {
if (!PL_initav)
PL_initav = newAV();
DEBUG_x( dump_sub(gv) );
- av_push(PL_initav, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ if (PL_main_start && ckWARN(WARN_VOID))
+ Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block");
+ av_push(PL_initav, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
}
=cut
*/
-void
+CV *
Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
{
- dTHR;
+ CV* cv;
ENTER;
- SAVECOPLINE(PL_curcop);
- SAVEHINTS();
+ SAVECOPLINE(PL_curcop);
CopLINE_set(PL_curcop, PL_copline);
+
+ SAVEHINTS();
PL_hints &= ~HINT_BLOCK_SCOPE;
if (stash) {
#endif
}
- newATTRSUB(
- start_subparse(FALSE, 0),
- newSVOP(OP_CONST, 0, newSVpv(name,0)),
- newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
- Nullop,
- newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
- );
+ cv = newXS(name, const_sv_xsub, __FILE__);
+ CvXSUBANY(cv).any_ptr = sv;
+ CvCONST_on(cv);
+ sv_setpv((SV*)cv, ""); /* prototype is "" */
LEAVE;
+
+ return cv;
}
/*
CV *
Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
{
- dTHR;
GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
register CV *cv;
- if (cv = (name ? GvCV(gv) : Nullcv)) {
+ if ((cv = (name ? GvCV(gv) : Nullcv))) {
if (GvCVGEN(gv)) {
/* just a cached method */
SvREFCNT_dec(cv);
line_t oldline = CopLINE(PL_curcop);
if (PL_copline != NOLINE)
CopLINE_set(PL_curcop, PL_copline);
- Perl_warner(aTHX_ WARN_REDEFINE, "Subroutine %s redefined",name);
+ Perl_warner(aTHX_ WARN_REDEFINE,
+ CvCONST(cv) ? "Constant subroutine %s redefined"
+ : "Subroutine %s redefined"
+ ,name);
CopLINE_set(PL_curcop, oldline);
}
SvREFCNT_dec(cv);
if (strEQ(s, "BEGIN")) {
if (!PL_beginav)
PL_beginav = newAV();
- av_push(PL_beginav, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_push(PL_beginav, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
else if (strEQ(s, "END")) {
if (!PL_endav)
PL_endav = newAV();
av_unshift(PL_endav, 1);
- av_store(PL_endav, 0, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_store(PL_endav, 0, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
else if (strEQ(s, "CHECK")) {
if (!PL_checkav)
PL_checkav = newAV();
+ if (PL_main_start && ckWARN(WARN_VOID))
+ Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block");
av_unshift(PL_checkav, 1);
- av_store(PL_checkav, 0, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ av_store(PL_checkav, 0, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
else if (strEQ(s, "INIT")) {
if (!PL_initav)
PL_initav = newAV();
- av_push(PL_initav, SvREFCNT_inc(cv));
- GvCV(gv) = 0;
+ if (PL_main_start && ckWARN(WARN_VOID))
+ Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block");
+ av_push(PL_initav, (SV*)cv);
+ GvCV(gv) = 0; /* cv has been hijacked */
}
}
else
void
Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
{
- dTHR;
register CV *cv;
char *name;
GV *gv;
name = "STDOUT";
gv = gv_fetchpv(name,TRUE, SVt_PVFM);
GvMULTI_on(gv);
- if (cv = GvFORM(gv)) {
+ if ((cv = GvFORM(gv))) {
if (ckWARN(WARN_REDEFINE)) {
line_t oldline = CopLINE(PL_curcop);
OP *
Perl_oopsHV(pTHX_ OP *o)
{
- dTHR;
-
switch (o->op_type) {
case OP_PADSV:
case OP_PADAV:
}
OP *
+Perl_ck_exit(pTHX_ OP *o)
+{
+#ifdef VMS
+ HV *table = GvHV(PL_hintgv);
+ if (table) {
+ SV **svp = hv_fetch(table, "vmsish_exit", 11, FALSE);
+ if (svp && *svp && SvTRUE(*svp))
+ o->op_private |= OPpEXIT_VMSISH;
+ }
+#endif
+ return ck_fun(o);
+}
+
+OP *
Perl_ck_exec(pTHX_ OP *o)
{
OP *kid;
OP *
Perl_ck_rvconst(pTHX_ register OP *o)
{
- dTHR;
SVOP *kid = (SVOP*)cUNOPo->op_first;
o->op_private |= (PL_hints & HINT_STRICT_REFS);
break;
}
if (badthing)
- Perl_croak(aTHX_
+ Perl_croak(aTHX_
"Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
name, badthing);
}
#ifdef USE_ITHREADS
/* XXX hack: dependence on sizeof(PADOP) <= sizeof(SVOP) */
kPADOP->op_padix = pad_alloc(OP_GV, SVs_PADTMP);
+ SvREFCNT_dec(PL_curpad[kPADOP->op_padix]);
GvIN_PAD_on(gv);
PL_curpad[kPADOP->op_padix] = SvREFCNT_inc(gv);
#else
kid->op_sv = SvREFCNT_inc(gv);
#endif
+ kid->op_private = 0;
kid->op_ppaddr = PL_ppaddr[OP_GV];
}
}
OP *
Perl_ck_ftst(pTHX_ OP *o)
{
- dTHR;
I32 type = o->op_type;
if (o->op_flags & OPf_REF) {
OP *
Perl_ck_fun(pTHX_ OP *o)
{
- dTHR;
register OP *kid;
OP **tokid;
OP *sibl;
tokid = &cLISTOPo->op_first;
kid = cLISTOPo->op_first;
if (kid->op_type == OP_PUSHMARK ||
- kid->op_type == OP_NULL && kid->op_targ == OP_PUSHMARK)
+ (kid->op_type == OP_NULL && kid->op_targ == OP_PUSHMARK))
{
tokid = &kid->op_sibling;
kid = kid->op_sibling;
name = GvNAME(gv);
len = GvNAMELEN(gv);
}
+ else if (kid->op_type == OP_AELEM
+ || kid->op_type == OP_HELEM)
+ {
+ name = "__ANONIO__";
+ len = 10;
+ mod(kid,type);
+ }
if (name) {
SV *namesv;
targ = pad_alloc(OP_RV2GV, SVs_PADTMP);
namesv = PL_curpad[targ];
- SvUPGRADE(namesv, SVt_PV);
+ (void)SvUPGRADE(namesv, SVt_PV);
if (*name != '$')
sv_setpvn(namesv, "$", 1);
sv_catpvn(namesv, name, len);
#if !defined(PERL_EXTERNAL_GLOB)
/* XXX this can be tightened up and made more failsafe. */
if (!gv) {
- OP *modname = newSVOP(OP_CONST, 0, newSVpvn("File::Glob", 10));
- modname->op_private |= OPpCONST_BARE;
ENTER;
- utilize(1, start_subparse(FALSE, 0), Nullop, modname,
- newSVOP(OP_CONST, 0, newSVpvn(":globally", 9)));
+ Perl_load_module(aTHX_ 0, newSVpvn("File::Glob", 10), Nullsv,
+ /* null-terminated import list */
+ newSVpvn(":globally", 9), Nullsv);
gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
LEAVE;
}
OP *
Perl_ck_defined(pTHX_ OP *o) /* 19990527 MJD */
{
- dTHR;
if ((o->op_flags & OPf_KIDS) && ckWARN(WARN_DEPRECATED)) {
switch (cUNOPo->op_first->op_type) {
case OP_RV2AV:
- break; /* Globals via GV can be undef */
+ /* This is needed for
+ if (defined %stash::)
+ to work. Do not break Tk.
+ */
+ break; /* Globals via GV can be undef */
case OP_PADAV:
case OP_AASSIGN: /* Is this a good idea? */
Perl_warner(aTHX_ WARN_DEPRECATED,
"defined(@array) is deprecated");
Perl_warner(aTHX_ WARN_DEPRECATED,
- "(Maybe you should just omit the defined()?)\n");
+ "\t(Maybe you should just omit the defined()?)\n");
break;
case OP_RV2HV:
- break; /* Globals via GV can be undef */
+ /* This is needed for
+ if (defined %stash::)
+ to work. Do not break Tk.
+ */
+ break; /* Globals via GV can be undef */
case OP_PADHV:
Perl_warner(aTHX_ WARN_DEPRECATED,
"defined(%%hash) is deprecated");
Perl_warner(aTHX_ WARN_DEPRECATED,
- "(Maybe you should just omit the defined()?)\n");
+ "\t(Maybe you should just omit the defined()?)\n");
break;
default:
/* no warning */
SV* sv = kSVOP->op_sv;
if (!(strchr(SvPVX(sv), ':') || strchr(SvPVX(sv), '\''))) {
OP *cmop;
- sv_upgrade(sv, SVt_PVIV);
- SvIOK_on(sv);
- PERL_HASH(SvUVX(sv), SvPVX(sv), SvCUR(sv));
+ if (!SvREADONLY(sv) || !SvFAKE(sv)) {
+ sv = newSVpvn_share(SvPVX(sv), SvCUR(sv), 0);
+ }
+ else {
+ kSVOP->op_sv = Nullsv;
+ }
cmop = newSVOP(OP_METHOD_NAMED, 0, sv);
- kSVOP->op_sv = Nullsv;
op_free(o);
return cmop;
}
}
OP *
+Perl_ck_open(pTHX_ OP *o)
+{
+ HV *table = GvHV(PL_hintgv);
+ if (table) {
+ SV **svp;
+ I32 mode;
+ svp = hv_fetch(table, "open_IN", 7, FALSE);
+ if (svp && *svp) {
+ mode = mode_from_discipline(*svp);
+ if (mode & O_BINARY)
+ o->op_private |= OPpOPEN_IN_RAW;
+ else if (mode & O_TEXT)
+ o->op_private |= OPpOPEN_IN_CRLF;
+ }
+
+ svp = hv_fetch(table, "open_OUT", 8, FALSE);
+ if (svp && *svp) {
+ mode = mode_from_discipline(*svp);
+ if (mode & O_BINARY)
+ o->op_private |= OPpOPEN_OUT_RAW;
+ else if (mode & O_TEXT)
+ o->op_private |= OPpOPEN_OUT_CRLF;
+ }
+ }
+ if (o->op_type == OP_BACKTICK)
+ return o;
+ return ck_fun(o);
+}
+
+OP *
Perl_ck_repeat(pTHX_ OP *o)
{
if (cBINOPo->op_first->op_flags & OPf_PARENS) {
--SvCUR(kid->op_sv);
}
}
- sv_catpvn(kid->op_sv, ".pm", 3);
+ if (SvREADONLY(kid->op_sv)) {
+ SvREADONLY_off(kid->op_sv);
+ sv_catpvn(kid->op_sv, ".pm", 3);
+ SvREADONLY_on(kid->op_sv);
+ }
+ else
+ sv_catpvn(kid->op_sv, ".pm", 3);
}
}
return ck_fun(o);
}
+OP *
+Perl_ck_return(pTHX_ OP *o)
+{
+ OP *kid;
+ if (CvLVALUE(PL_compcv)) {
+ for (kid = cLISTOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
+ mod(kid, OP_LEAVESUBLV);
+ }
+ return o;
+}
+
#if 0
OP *
Perl_ck_retarget(pTHX_ OP *o)
OP *
Perl_ck_sort(pTHX_ OP *o)
{
+ OP *firstkid;
o->op_private = 0;
#ifdef USE_LOCALE
if (PL_hints & HINT_LOCALE)
if (o->op_type == OP_SORT && o->op_flags & OPf_STACKED)
simplify_sort(o);
- if (o->op_flags & OPf_STACKED) { /* may have been cleared */
- OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
+ firstkid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
+ if (o->op_flags & OPf_STACKED) { /* may have been cleared */
OP *k;
- kid = kUNOP->op_first; /* get past null */
+ OP *kid = cUNOPx(firstkid)->op_first; /* get past null */
if (kid->op_type == OP_SCOPE || kid->op_type == OP_LEAVE) {
linklist(kid);
for (k = kLISTOP->op_first->op_next; k; k = k->op_next) {
if (k->op_next == kid)
k->op_next = 0;
+ /* don't descend into loops */
+ else if (k->op_type == OP_ENTERLOOP
+ || k->op_type == OP_ENTERITER)
+ {
+ k = cLOOPx(k)->op_lastop;
+ }
}
}
else
}
peep(k);
- kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
- if (o->op_type == OP_SORT)
+ kid = firstkid;
+ if (o->op_type == OP_SORT) {
+ /* provide scalar context for comparison function/block */
+ kid = scalar(kid);
kid->op_next = kid;
+ }
else
kid->op_next = k;
o->op_flags |= OPf_SPECIAL;
}
else if (kid->op_type == OP_RV2SV || kid->op_type == OP_PADSV)
- null(cLISTOPo->op_first->op_sibling);
+ null(firstkid);
+
+ firstkid = firstkid->op_sibling;
}
+ /* provide list context for arguments */
+ if (o->op_type == OP_SORT)
+ list(firstkid);
+
return o;
}
STATIC void
S_simplify_sort(pTHX_ OP *o)
{
- dTHR;
register OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
OP *k;
int reversed;
GV *gv;
if (!(o->op_flags & OPf_STACKED))
return;
- GvMULTI_on(gv_fetchpv("a", TRUE, SVt_PV));
- GvMULTI_on(gv_fetchpv("b", TRUE, SVt_PV));
+ GvMULTI_on(gv_fetchpv("a", TRUE, SVt_PV));
+ GvMULTI_on(gv_fetchpv("b", TRUE, SVt_PV));
kid = kUNOP->op_first; /* get past null */
if (kid->op_type != OP_SCOPE)
return;
kid = cLISTOPo->op_first->op_sibling;
cLISTOPo->op_first->op_sibling = kid->op_sibling; /* bypass old block */
op_free(kid); /* then delete it */
- cLISTOPo->op_children--;
}
OP *
cLISTOPo->op_last = kid; /* There was only one element previously */
}
- if (kid->op_type != OP_MATCH) {
+ if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) {
OP *sibl = kid->op_sibling;
kid->op_sibling = 0;
kid = pmruntime( newPMOP(OP_MATCH, OPf_SPECIAL), kid, Nullop);
}
OP *
-Perl_ck_join(pTHX_ OP *o)
+Perl_ck_join(pTHX_ OP *o)
{
if (ckWARN(WARN_SYNTAX)) {
OP *kid = cLISTOPo->op_first->op_sibling;
OP *
Perl_ck_subr(pTHX_ OP *o)
{
- dTHR;
OP *prev = ((cUNOPo->op_first->op_sibling)
? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first;
OP *o2 = prev->op_sibling;
proto++;
arg++;
if (o2->op_type != OP_REFGEN && o2->op_type != OP_UNDEF)
- bad_type(arg, "block", gv_ename(namegv), o2);
+ bad_type(arg,
+ arg == 1 ? "block or sub {}" : "sub {}",
+ gv_ename(namegv), o2);
break;
case '*':
/* '*' allows any scalar type, including bareword */
bad_type(arg, "symbol", gv_ename(namegv), o2);
goto wrapref;
case '&':
- if (o2->op_type != OP_RV2CV)
- bad_type(arg, "sub", gv_ename(namegv), o2);
+ if (o2->op_type != OP_ENTERSUB)
+ bad_type(arg, "subroutine entry", gv_ename(namegv), o2);
goto wrapref;
case '$':
if (o2->op_type != OP_RV2SV
return ck_fun(o);
}
+OP *
+Perl_ck_substr(pTHX_ OP *o)
+{
+ o = ck_fun(o);
+ if ((o->op_flags & OPf_KIDS) && o->op_private == 4) {
+ OP *kid = cLISTOPo->op_first;
+
+ if (kid->op_type == OP_NULL)
+ kid = kid->op_sibling;
+ if (kid)
+ kid->op_flags |= OPf_MOD;
+
+ }
+ return o;
+}
+
/* A peephole optimizer. We visit the ops in the order they're to execute. */
void
Perl_peep(pTHX_ register OP *o)
{
- dTHR;
register OP* oldop = 0;
STRLEN n_a;
- OP *last_composite = Nullop;
if (!o || o->op_seq)
return;
case OP_DBSTATE:
PL_curcop = ((COP*)o); /* for warnings */
o->op_seq = PL_op_seqmax++;
- last_composite = Nullop;
break;
case OP_CONST:
* for reference counts, sv_upgrade() etc. */
if (cSVOP->op_sv) {
PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
- SvREFCNT_dec(PL_curpad[ix]);
- SvPADTMP_on(cSVOPo->op_sv);
- PL_curpad[ix] = cSVOPo->op_sv;
+ if (SvPADTMP(cSVOPo->op_sv)) {
+ /* If op_sv is already a PADTMP then it is being used by
+ * some pad, so make a copy. */
+ sv_setsv(PL_curpad[ix],cSVOPo->op_sv);
+ SvREADONLY_on(PL_curpad[ix]);
+ SvREFCNT_dec(cSVOPo->op_sv);
+ }
+ else {
+ SvREFCNT_dec(PL_curpad[ix]);
+ SvPADTMP_on(cSVOPo->op_sv);
+ PL_curpad[ix] = cSVOPo->op_sv;
+ /* XXX I don't know how this isn't readonly already. */
+ SvREADONLY_on(PL_curpad[ix]);
+ }
cSVOPo->op_sv = Nullsv;
o->op_targ = ix;
}
#endif
- /* FALL THROUGH */
- case OP_UC:
- case OP_UCFIRST:
- case OP_LC:
- case OP_LCFIRST:
+ 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 */
goto ignore_optimization;
else {
+ /* assert(PL_opargs[o->op_type] & OA_TARGLEX); */
o->op_targ = o->op_next->op_targ;
o->op_next->op_targ = 0;
o->op_private |= OPpTARGET_MY;
(PL_op = pop->op_next) &&
pop->op_next->op_type == OP_AELEM &&
!(pop->op_next->op_private &
- (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF)) &&
+ (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)) &&
(i = SvIV(((SVOP*)pop)->op_sv) - PL_compiling.cop_arybase)
<= 255 &&
i >= 0)
case OP_ENTERLOOP:
o->op_seq = PL_op_seqmax++;
+ while (cLOOP->op_redoop->op_type == OP_NULL)
+ cLOOP->op_redoop = cLOOP->op_redoop->op_next;
peep(cLOOP->op_redoop);
+ while (cLOOP->op_nextop->op_type == OP_NULL)
+ cLOOP->op_nextop = cLOOP->op_nextop->op_next;
peep(cLOOP->op_nextop);
+ while (cLOOP->op_lastop->op_type == OP_NULL)
+ cLOOP->op_lastop = cLOOP->op_lastop->op_next;
peep(cLOOP->op_lastop);
break;
case OP_MATCH:
case OP_SUBST:
o->op_seq = PL_op_seqmax++;
+ while (cPMOP->op_pmreplstart &&
+ cPMOP->op_pmreplstart->op_type == OP_NULL)
+ cPMOP->op_pmreplstart = cPMOP->op_pmreplstart->op_next;
peep(cPMOP->op_pmreplstart);
break;
case OP_EXEC:
o->op_seq = PL_op_seqmax++;
- if (ckWARN(WARN_SYNTAX) && o->op_next
+ if (ckWARN(WARN_SYNTAX) && o->op_next
&& o->op_next->op_type == OP_NEXTSTATE) {
if (o->op_next->op_sibling &&
o->op_next->op_sibling->op_type != OP_EXIT &&
Perl_warner(aTHX_ WARN_EXEC,
"Statement unlikely to be reached");
Perl_warner(aTHX_ WARN_EXEC,
- "(Maybe you meant system() when you said exec()?)\n");
+ "\t(Maybe you meant system() when you said exec()?)\n");
CopLINE_set(PL_curcop, oldline);
}
}
GV **fields;
SV **svp, **indsvp, *sv;
I32 ind;
- char *key;
+ char *key = NULL;
STRLEN keylen;
o->op_seq = PL_op_seqmax++;
- if ((o->op_private & (OPpLVAL_INTRO))
- || ((BINOP*)o)->op_last->op_type != OP_CONST)
+
+ if (((BINOP*)o)->op_last->op_type != OP_CONST)
+ break;
+
+ /* Make the CONST have a shared SV */
+ svp = cSVOPx_svp(((BINOP*)o)->op_last);
+ if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) {
+ key = SvPV(sv, keylen);
+ if (SvUTF8(sv))
+ keylen = -keylen;
+ lexname = newSVpvn_share(key, keylen, 0);
+ SvREFCNT_dec(sv);
+ *svp = lexname;
+ }
+
+ if ((o->op_private & (OPpLVAL_INTRO)))
break;
+
rop = (UNOP*)((BINOP*)o)->op_first;
if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
break;
fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
if (!fields || !GvHV(*fields))
break;
- svp = cSVOPx_svp(((BINOP*)o)->op_last);
key = SvPV(*svp, keylen);
+ if (SvUTF8(*svp))
+ keylen = -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_op = (SVOP*)key_op->op_sibling) {
svp = cSVOPx_svp(key_op);
key = SvPV(*svp, keylen);
+ if (SvUTF8(*svp))
+ keylen = -keylen;
indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
if (!indsvp) {
Perl_croak(aTHX_ "No such pseudo-hash field \"%s\" "
break;
}
- case OP_RV2AV:
- case OP_RV2HV:
- if (!(o->op_flags & OPf_WANT)
- || (o->op_flags & OPf_WANT) == OPf_WANT_LIST)
- {
- last_composite = o;
- }
- o->op_seq = PL_op_seqmax++;
- break;
-
- case OP_RETURN:
- if (o->op_next && o->op_next->op_type != OP_LEAVESUBLV) {
- o->op_seq = PL_op_seqmax++;
- break;
- }
- /* FALL THROUGH */
-
- case OP_LEAVESUBLV:
- if (last_composite) {
- OP *r = last_composite;
-
- while (r->op_sibling)
- r = r->op_sibling;
- if (r->op_next == o
- || (r->op_next->op_type == OP_LIST
- && r->op_next->op_next == o))
- {
- if (last_composite->op_type == OP_RV2AV)
- yyerror("Lvalue subs returning arrays not implemented yet");
- else
- yyerror("Lvalue subs returning hashes not implemented yet");
- ;
- }
- }
- /* FALL THROUGH */
-
default:
o->op_seq = PL_op_seqmax++;
break;
}
LEAVE;
}
+
+#include "XSUB.h"
+
+/* Efficient sub that returns a constant scalar value. */
+static void
+const_sv_xsub(pTHXo_ CV* cv)
+{
+ dXSARGS;
+ EXTEND(sp, 1);
+ ST(0) = (SV*)XSANY.any_ptr;
+ XSRETURN(1);
+}