#include "EXTERN.h"
#define PERL_IN_PP_HOT_C
#include "perl.h"
+#include "regcomp.h"
/* Hot code. */
for ease of testing and setting) */
/* for each arg, holds the result of an SvPV() call */
struct multiconcat_svpv {
- char *pv;
+ const char *pv;
SSize_t len;
}
*targ_chain, /* chain of slots where targ has appeared on RHS */
/* an undef value in the presence of warnings may trigger
* side affects */
goto do_magical;
- svpv_end->pv = (char*)"";
+ svpv_end->pv = "";
len = 0;
}
else
* one set of segment lengths.
*
* * If the string has different plain and utf8 representations
- * (e.g. "\x80"), then then aux[PERL_MULTICONCAT_IX_PLAIN_PV/LEN]]
+ * (e.g. "\x80"), then aux[PERL_MULTICONCAT_IX_PLAIN_PV/LEN]]
* holds the plain rep, while aux[PERL_MULTICONCAT_IX_UTF8_PV/LEN]
* holds the utf8 rep, and there are 2 sets of segment lengths,
* with the utf8 set following after the plain set.
* calculate how much extra growth is needed for all the chars
* which will expand to two utf8 bytes.
* Also, if the growth is non-zero, negate the length to indicate
- * that this this is a variant string. Conversely, un-negate the
+ * that this is a variant string. Conversely, un-negate the
* length on utf8 args (which was only needed to flag non-utf8
* args in this loop */
for (svpv_p = svpv_buf; svpv_p < svpv_end; svpv_p++) {
SV * const tmpsv = amagic_call(left, right, concat_amg,
(nextappend ? AMGf_assign: 0));
if (tmpsv) {
- /* NB: tryAMAGICbin_MG() includes an SvPADMY test
- * here, which isn;t needed as any implicit
- * assign does under OPpTARGET_MY is done after
+ /* NB: tryAMAGICbin_MG() includes an OPpTARGET_MY test
+ * here, which isn't needed as any implicit
+ * assign done under OPpTARGET_MY is done after
* this loop */
if (nextappend) {
sv_setsv(left, tmpsv);
SP = toparg - stack_adj + 1;
- /* Assign result of all RHS concats (left) to LHS (targ).
+ /* Return the result of all RHS concats, unless this op includes
+ * an assign ($lex = x.y.z or expr = x.y.z), in which case copy
+ * to target (which will be $lex or expr).
* If we are appending, targ will already have been appended to in
* the loop */
- if (is_append)
- SvTAINT(targ);
- else {
+ if ( !is_append
+ && ( (PL_op->op_flags & OPf_STACKED)
+ || (PL_op->op_private & OPpTARGET_MY))
+ ) {
sv_setsv(targ, left);
SvSETMAGIC(targ);
}
+ else
+ targ = left;
SETs(targ);
RETURN;
}
{
dSP;
SV *left, *right;
+ U32 flags_and, flags_or;
- tryAMAGICbin_MG(eq_amg, AMGf_set|AMGf_numeric);
+ tryAMAGICbin_MG(eq_amg, AMGf_numeric);
right = POPs;
left = TOPs;
+ flags_and = SvFLAGS(left) & SvFLAGS(right);
+ flags_or = SvFLAGS(left) | SvFLAGS(right);
+
SETs(boolSV(
- (SvIOK_notUV(left) && SvIOK_notUV(right))
- ? (SvIVX(left) == SvIVX(right))
- : ( do_ncmp(left, right) == 0)
+ ( (flags_and & SVf_IOK) && ((flags_or & SVf_IVisUV) ==0 ) )
+ ? (SvIVX(left) == SvIVX(right))
+ : (flags_and & SVf_NOK)
+ ? (SvNVX(left) == SvNVX(right))
+ : ( do_ncmp(left, right) == 0)
));
RETURN;
}
NV nl = SvNVX(svl);
NV nr = SvNVX(svr);
- if (
-#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
- !Perl_isnan(nl) && nl == (NV)(il = (IV)nl)
- && !Perl_isnan(nr) && nr == (NV)(ir = (IV)nr)
-#else
- nl == (NV)(il = (IV)nl) && nr == (NV)(ir = (IV)nr)
-#endif
- )
+ if (lossless_NV_to_IV(nl, &il) && lossless_NV_to_IV(nr, &ir)) {
/* nothing was lost by converting to IVs */
goto do_iv;
+ }
SP--;
TARGn(nl + nr, 0); /* args not GMG, so can't be tainted */
SETs(TARG);
auv = aiv;
auvok = 1; /* Now acting as a sign flag. */
} else {
- auv = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv);
+ /* Using 0- here and later to silence bogus warning
+ * from MS VC */
+ auv = (UV) (0 - (UV) aiv);
}
}
a_valid = 1;
buv = biv;
buvok = 1;
} else
- buv = (biv == IV_MIN) ? (UV)biv : (UV)(-biv);
+ buv = (UV) (0 - (UV) biv);
}
/* ?uvok if value is >= 0. basically, flagged as UV if it's +ve,
else "IV" now, independent of how it came in.
PUSHi(i);
}
else
-#ifdef PERL_OP_PARENT
if (is_keys) {
/* parent op should be an unused OP_KEYS whose targ we can
* use */
PUSHi(i);
}
else
-#endif
mPUSHi(i);
}
}
#endif
)
{
- dVAR;
SV **relem;
SV **lelem;
SSize_t lcount = lastlelem - firstlelem + 1;
PP(pp_aassign)
{
- dVAR; dSP;
+ dSP;
SV **lastlelem = PL_stack_sp;
SV **lastrelem = PL_stack_base + POPMARK;
SV **firstrelem = PL_stack_base + POPMARK + 1;
if (!SvIMMORTAL(lsv)) {
sv_set_undef(lsv);
SvSETMAGIC(lsv);
- *relem++ = lsv;
}
+ *relem++ = lsv;
break;
} /* switch */
} /* while */
RETURN;
}
+STATIC bool
+S_are_we_in_Debug_EXECUTE_r(pTHX)
+{
+ /* Given a 'use re' is in effect, does it ask for outputting execution
+ * debug info?
+ *
+ * This is separated from the sole place it's called, an inline function,
+ * because it is the large-ish slow portion of the function */
+
+ DECLARE_AND_GET_RE_DEBUG_FLAGS_NON_REGEX;
+
+ return cBOOL(RE_DEBUG_FLAG(RE_DEBUG_EXECUTE_MASK));
+}
+
+PERL_STATIC_INLINE bool
+S_should_we_output_Debug_r(pTHX_ regexp *prog)
+{
+ PERL_ARGS_ASSERT_SHOULD_WE_OUTPUT_DEBUG_R;
+
+ /* pp_match can output regex debugging info. This function returns a
+ * boolean as to whether or not it should.
+ *
+ * Under -Dr, it should. Any reasonable compiler will optimize this bit of
+ * code away on non-debugging builds. */
+ if (UNLIKELY(DEBUG_r_TEST)) {
+ return TRUE;
+ }
+
+ /* If the regex engine is using the non-debugging execution routine, then
+ * no debugging should be output. Same if the field is NULL that pluggable
+ * engines are not supposed to fill. */
+ if ( LIKELY(prog->engine->exec == &Perl_regexec_flags)
+ || UNLIKELY(prog->engine->op_comp == NULL))
+ {
+ return FALSE;
+ }
+
+ /* Otherwise have to check */
+ return S_are_we_in_Debug_EXECUTE_r(aTHX);
+}
+
PP(pp_match)
{
dSP; dTARG;
pm->op_pmflags & PMf_USED
#endif
) {
- DEBUG_r(PerlIO_printf(Perl_debug_log, "?? already matched once"));
+ if (UNLIKELY(should_we_output_Debug_r(prog))) {
+ PerlIO_printf(Perl_debug_log, "?? already matched once");
+ }
goto nope;
}
}
if (RXp_MINLEN(prog) >= 0 && (STRLEN)RXp_MINLEN(prog) > len) {
- DEBUG_r(PerlIO_printf(Perl_debug_log, "String shorter than min possible regex match (%"
- UVuf " < %" IVdf ")\n",
- (UV)len, (IV)RXp_MINLEN(prog)));
+ if (UNLIKELY(should_we_output_Debug_r(prog))) {
+ PerlIO_printf(Perl_debug_log,
+ "String shorter than min possible regex match (%zd < %zd)\n",
+ len, RXp_MINLEN(prog));
+ }
goto nope;
}
if (IoFLAGS(io) & IOf_ARGV) {
if (IoFLAGS(io) & IOf_START) {
IoLINES(io) = 0;
- if (av_tindex(GvAVn(PL_last_in_gv)) < 0) {
+ if (av_count(GvAVn(PL_last_in_gv)) == 0) {
IoFLAGS(io) &= ~IOf_START;
do_open6(PL_last_in_gv, "-", 1, NULL, NULL, 0);
SvTAINTED_off(GvSVn(PL_last_in_gv)); /* previous tainting irrelevant */
}
for (t1 = SvPVX_const(sv); *t1; t1++)
#ifdef __VMS
- if (strchr("*%?", *t1))
+ if (memCHRs("*%?", *t1))
#else
- if (strchr("$&*(){}[]'\";\\|?<>~`", *t1))
+ if (memCHRs("$&*(){}[]'\";\\|?<>~`", *t1))
#endif
break;
if (*t1 && PerlLIO_lstat(SvPVX_const(sv), &statbuf) < 0) {
IV len;
if (!defer)
DIE(aTHX_ PL_no_aelem, elem);
- len = av_tindex(av);
+ len = av_top_index(av);
/* Resolve a negative index that falls within
* the array. Leave it negative it if falls
* outside the array. */
case CXt_LOOP_LIST: /* for (1,2,3) */
assert(OPpITER_REVERSED == 2); /* so inc becomes -1 or 1 */
- inc = 1 - (PL_op->op_private & OPpITER_REVERSED);
+ inc = (IV)1 - (IV)(PL_op->op_private & OPpITER_REVERSED);
ix = (cx->blk_loop.state_u.stack.ix += inc);
if (UNLIKELY(inc > 0
? ix > cx->blk_oldsp
case CXt_LOOP_ARY: /* for (@ary) */
av = cx->blk_loop.state_u.ary.ary;
- inc = 1 - (PL_op->op_private & OPpITER_REVERSED);
+ inc = (IV)1 - (IV)(PL_op->op_private & OPpITER_REVERSED);
ix = (cx->blk_loop.state_u.ary.ix += inc);
if (UNLIKELY(inc > 0
? ix > AvFILL(av)
DIE(aTHX_ "panic: pp_iter, type=%u", CxTYPE(cx));
}
- /* Bypass pushing &PL_sv_yes and calling pp_and(); instead
+ /* Try to bypass pushing &PL_sv_yes and calling pp_and(); instead
* jump straight to the AND op's op_other */
assert(PL_op->op_next->op_type == OP_AND);
- assert(PL_op->op_next->op_ppaddr == Perl_pp_and);
- return cLOGOPx(PL_op->op_next)->op_other;
+ if (PL_op->op_next->op_ppaddr == Perl_pp_and) {
+ return cLOGOPx(PL_op->op_next)->op_other;
+ }
+ else {
+ /* An XS module has replaced the op_ppaddr, so fall back to the slow,
+ * obvious way. */
+ /* pp_enteriter should have pre-extended the stack */
+ EXTEND_SKIP(PL_stack_sp, 1);
+ *++PL_stack_sp = &PL_sv_yes;
+ return PL_op->op_next;
+ }
retno:
- /* Bypass pushing &PL_sv_no and calling pp_and(); instead
+ /* Try to bypass pushing &PL_sv_no and calling pp_and(); instead
* jump straight to the AND op's op_next */
assert(PL_op->op_next->op_type == OP_AND);
- assert(PL_op->op_next->op_ppaddr == Perl_pp_and);
/* pp_enteriter should have pre-extended the stack */
EXTEND_SKIP(PL_stack_sp, 1);
/* we only need this for the rare case where the OP_AND isn't
* in void context, e.g. $x = do { for (..) {...} };
- * but its cheaper to just push it rather than testing first
+ * (or for when an XS module has replaced the op_ppaddr)
+ * but it's cheaper to just push it rather than testing first
*/
*++PL_stack_sp = &PL_sv_no;
- return PL_op->op_next->op_next;
+ if (PL_op->op_next->op_ppaddr == Perl_pp_and) {
+ return PL_op->op_next->op_next;
+ }
+ else {
+ /* An XS module has replaced the op_ppaddr, so fall back to the slow,
+ * obvious way. */
+ return PL_op->op_next;
+ }
}
void
Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, U8 gimme, int pass)
{
- dVAR;
dSP;
SSize_t tmps_base; /* lowest index into tmps stack that needs freeing now */
SSize_t nargs;
else if (SvNOK(elemsv))
elem = (IV)SvNV(elemsv);
if (elem > 0) {
- static const char oom_array_extend[] =
- "Out of memory during array extend"; /* Duplicated in av.c */
- MEM_WRAP_CHECK_1(elem,SV*,oom_array_extend);
+ MEM_WRAP_CHECK_s(elem,SV*,"Out of memory during array extend");
}
#endif
if (!svp || !*svp) {
IV len;
if (!defer)
DIE(aTHX_ PL_no_aelem, elem);
- len = av_tindex(av);
+ len = av_top_index(av);
/* Resolve a negative index that falls within the array. Leave
it negative it if falls outside the array. */
if (elem < 0 && len + elem >= 0)