PP(pp_wantarray)
{
- dVAR;
dSP;
I32 cxix;
const PERL_CONTEXT *cx;
PP(pp_regcreset)
{
- dVAR;
TAINT_NOT;
return NORMAL;
}
PP(pp_regcomp)
{
- dVAR;
dSP;
PMOP *pm = (PMOP*)cLOGOP->op_other;
SV **args;
const bool was_tainted = TAINT_get;
if (pm->op_flags & OPf_STACKED)
lhs = args[-1];
- else if (pm->op_private & OPpTARGET_MY)
+ else if (pm->op_targ)
lhs = PAD_SV(pm->op_targ);
else lhs = DEFSV;
SvGETMAGIC(lhs);
modified by get-magic), to avoid incorrectly setting the
RXf_TAINTED flag with RX_TAINT_on further down. */
TAINT_set(was_tainted);
-#if NO_TAINT_SUPPORT
+#ifdef NO_TAINT_SUPPORT
PERL_UNUSED_VAR(was_tainted);
#endif
}
}
-#ifndef INCOMPLETE_TAINTS
if (TAINTING_get && TAINT_get) {
SvTAINTED_on((SV*)new_re);
RX_TAINT_on(new_re);
}
-#endif
#if !defined(USE_ITHREADS)
/* can't change the optree at runtime either */
PP(pp_substcont)
{
- dVAR;
dSP;
PERL_CONTEXT *cx = &cxstack[cxstack_ix];
PMOP * const pm = (PMOP*) cLOGOP->op_other;
rxres_restore(&cx->sb_rxres, rx);
if (cx->sb_iters++) {
- const I32 saviters = cx->sb_iters;
+ const SSize_t saviters = cx->sb_iters;
if (cx->sb_iters > cx->sb_maxiters)
DIE(aTHX_ "Substitution loop");
POPSUBST(cx);
PERL_ASYNC_CHECK();
RETURNOP(pm->op_next);
- assert(0); /* NOTREACHED */
+ NOT_REACHED; /* NOTREACHED */
}
cx->sb_iters = saviters;
}
if (!(mg = mg_find_mglob(sv))) {
mg = sv_magicext_mglob(sv);
}
- assert(SvPOK(dstr));
- MgBYTEPOS_set(mg, sv, SvPVX(dstr), m - orig);
+ assert(SvPOK(sv));
+ MgBYTEPOS_set(mg, sv, SvPVX(sv), m - orig);
}
if (old != rx)
(void)ReREFCNT_inc(rx);
PP(pp_formline)
{
- dVAR; dSP; dMARK; dORIGMARK;
+ dSP; dMARK; dORIGMARK;
SV * const tmpForm = *++MARK;
SV *formsv; /* contains text of original format */
U32 *fpc; /* format ops program counter */
I32 arg;
SV *sv = NULL; /* current item */
const char *item = NULL;/* string value of current item */
- I32 itemsize = 0; /* length of current item, possibly truncated */
+ I32 itemsize = 0; /* length (chars) of item, possibly truncated */
+ I32 itembytes = 0; /* as itemsize, but length in bytes */
I32 fieldsize = 0; /* width of current field */
I32 lines = 0; /* number of lines that have been output */
bool chopspace = (strchr(PL_chopset, ' ') != NULL); /* does $: have space */
STRLEN linemark = 0; /* pos of start of line in output */
NV value;
bool gotsome = FALSE; /* seen at least one non-blank item on this line */
- STRLEN len;
+ STRLEN len; /* length of current sv */
STRLEN linemax; /* estimate of output size in bytes */
bool item_is_utf8 = FALSE;
bool targ_is_utf8 = FALSE;
PerlIO_printf(Perl_debug_log, "%-16s\n", name);
} );
switch (*fpc++) {
- case FF_LINEMARK:
+ case FF_LINEMARK: /* start (or end) of a line */
linemark = t - SvPVX(PL_formtarget);
lines++;
gotsome = FALSE;
break;
- case FF_LITERAL:
+ case FF_LITERAL: /* append <arg> literal chars */
to_copy = *fpc++;
source = (U8 *)f;
f += to_copy;
item_is_utf8 = targ_is_utf8 ? !!DO_UTF8(formsv) : !!SvUTF8(formsv);
goto append;
- case FF_SKIP:
+ case FF_SKIP: /* skip <arg> chars in format */
f += *fpc++;
break;
- case FF_FETCH:
+ case FF_FETCH: /* get next item and set field size to <arg> */
arg = *fpc++;
f += arg;
fieldsize = arg;
SvTAINTED_on(PL_formtarget);
break;
- case FF_CHECKNL:
+ case FF_CHECKNL: /* find max len of item (up to \n) that fits field */
{
- const char *send;
const char *s = item = SvPV_const(sv, len);
- itemsize = len;
- if (DO_UTF8(sv)) {
- itemsize = sv_len_utf8(sv);
- if (itemsize != (I32)len) {
- I32 itembytes;
- if (itemsize > fieldsize) {
- itemsize = fieldsize;
- itembytes = itemsize;
- sv_pos_u2b(sv, &itembytes, 0);
- }
- else
- itembytes = len;
- send = chophere = s + itembytes;
- while (s < send) {
- if (! isCNTRL(*s))
- gotsome = TRUE;
- else if (*s == '\n')
- break;
- s++;
- }
- item_is_utf8 = TRUE;
- itemsize = s - item;
- sv_pos_b2u(sv, &itemsize);
- break;
- }
- }
- item_is_utf8 = FALSE;
- if (itemsize > fieldsize)
- itemsize = fieldsize;
- send = chophere = s + itemsize;
- while (s < send) {
- if (! isCNTRL(*s))
- gotsome = TRUE;
- else if (*s == '\n')
- break;
- s++;
- }
- itemsize = s - item;
+ const char *send = s + len;
+
+ itemsize = 0;
+ item_is_utf8 = DO_UTF8(sv);
+ while (s < send) {
+ if (!isCNTRL(*s))
+ gotsome = TRUE;
+ else if (*s == '\n')
+ break;
+
+ if (item_is_utf8)
+ s += UTF8SKIP(s);
+ else
+ s++;
+ itemsize++;
+ if (itemsize == fieldsize)
+ break;
+ }
+ itembytes = s - item;
+ chophere = s;
break;
}
- case FF_CHECKCHOP:
+ case FF_CHECKCHOP: /* like CHECKNL, but up to highest split point */
{
const char *s = item = SvPV_const(sv, len);
- itemsize = len;
- if (DO_UTF8(sv)) {
- itemsize = sv_len_utf8(sv);
- if (itemsize != (I32)len) {
- I32 itembytes;
- if (itemsize <= fieldsize) {
- const char *send = chophere = s + itemsize;
- while (s < send) {
- if (*s == '\r') {
- itemsize = s - item;
- chophere = s;
- break;
- }
- if (! isCNTRL(*s))
- gotsome = TRUE;
- s++;
- }
- }
- else {
- const char *send;
- itemsize = fieldsize;
- itembytes = itemsize;
- sv_pos_u2b(sv, &itembytes, 0);
- send = chophere = s + itembytes;
- while (s < send || (s == send && isSPACE(*s))) {
- if (isSPACE(*s)) {
- if (chopspace)
- chophere = s;
- if (*s == '\r')
- break;
- }
- else {
- if (! isCNTRL(*s))
- gotsome = TRUE;
- if (strchr(PL_chopset, *s))
- chophere = s + 1;
- }
- s++;
- }
- itemsize = chophere - item;
- sv_pos_b2u(sv, &itemsize);
- }
- item_is_utf8 = TRUE;
- break;
- }
- }
- item_is_utf8 = FALSE;
- if (itemsize <= fieldsize) {
- const char *const send = chophere = s + itemsize;
- while (s < send) {
- if (*s == '\r') {
- itemsize = s - item;
- chophere = s;
- break;
- }
- if (! isCNTRL(*s))
- gotsome = TRUE;
+ const char *send = s + len;
+ I32 size = 0;
+
+ chophere = NULL;
+ item_is_utf8 = DO_UTF8(sv);
+ while (s < send) {
+ /* look for a legal split position */
+ if (isSPACE(*s)) {
+ if (*s == '\r') {
+ chophere = s;
+ itemsize = size;
+ break;
+ }
+ if (chopspace) {
+ /* provisional split point */
+ chophere = s;
+ itemsize = size;
+ }
+ /* we delay testing fieldsize until after we've
+ * processed the possible split char directly
+ * following the last field char; so if fieldsize=3
+ * and item="a b cdef", we consume "a b", not "a".
+ * Ditto further down.
+ */
+ if (size == fieldsize)
+ break;
+ }
+ else {
+ if (strchr(PL_chopset, *s)) {
+ /* provisional split point */
+ /* for a non-space split char, we include
+ * the split char; hence the '+1' */
+ chophere = s + 1;
+ itemsize = size;
+ }
+ if (size == fieldsize)
+ break;
+ if (!isCNTRL(*s))
+ gotsome = TRUE;
+ }
+
+ if (item_is_utf8)
+ s += UTF8SKIP(s);
+ else
s++;
- }
- }
- else {
- const char *send;
- itemsize = fieldsize;
- send = chophere = s + itemsize;
- while (s < send || (s == send && isSPACE(*s))) {
- if (isSPACE(*s)) {
- if (chopspace)
- chophere = s;
- if (*s == '\r')
- break;
- }
- else {
- if (! isCNTRL(*s))
- gotsome = TRUE;
- if (strchr(PL_chopset, *s))
- chophere = s + 1;
- }
- s++;
- }
- itemsize = chophere - item;
- }
+ size++;
+ }
+ if (!chophere || s == send) {
+ chophere = s;
+ itemsize = size;
+ }
+ itembytes = chophere - item;
+
break;
}
- case FF_SPACE:
+ case FF_SPACE: /* append padding space (diff of field, item size) */
arg = fieldsize - itemsize;
if (arg) {
fieldsize -= arg;
}
break;
- case FF_HALFSPACE:
+ case FF_HALFSPACE: /* like FF_SPACE, but only append half as many */
arg = fieldsize - itemsize;
if (arg) {
arg /= 2;
}
break;
- case FF_ITEM:
- to_copy = itemsize;
+ case FF_ITEM: /* append a text item, while blanking ctrl chars */
+ to_copy = itembytes;
source = (U8 *)item;
trans = 1;
- if (item_is_utf8) {
- /* convert to_copy from chars to bytes */
- U8 *s = source;
- while (to_copy--)
- s += UTF8SKIP(s);
- to_copy = s - source;
- }
goto append;
- case FF_CHOP:
- {
+ case FF_CHOP: /* (for ^*) chop the current item */
+ if (sv != &PL_sv_no) {
const char *s = chophere;
if (chopspace) {
while (isSPACE(*s))
s++;
}
- sv_chop(sv,s);
+ if (SvPOKp(sv))
+ sv_chop(sv,s);
+ else
+ /* tied, overloaded or similar strangeness.
+ * Do it the hard way */
+ sv_setpvn(sv, s, len - (s-item));
SvSETMAGIC(sv);
break;
}
- case FF_LINESNGL:
+ case FF_LINESNGL: /* process ^* */
chopspace = 0;
- case FF_LINEGLOB:
+ /* FALLTHROUGH */
+
+ case FF_LINEGLOB: /* process @* */
{
const bool oneline = fpc[-1] == FF_LINESNGL;
const char *s = item = SvPV_const(sv, len);
const char *const send = s + len;
item_is_utf8 = DO_UTF8(sv);
+ chophere = s + len;
if (!len)
break;
trans = 0;
gotsome = TRUE;
- chophere = s + len;
source = (U8 *) s;
to_copy = len;
while (s < send) {
if (*s++ == '\n') {
if (oneline) {
- to_copy = s - SvPVX_const(sv) - 1;
+ to_copy = s - item - 1;
chophere = s;
break;
} else {
break;
}
- case FF_0DECIMAL:
+ case FF_0DECIMAL: /* like FF_DECIMAL but for 0### */
arg = *fpc++;
-#if defined(USE_LONG_DOUBLE)
- fmt = (const char *)
- ((arg & FORM_NUM_POINT) ?
- "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl);
-#else
fmt = (const char *)
- ((arg & FORM_NUM_POINT) ?
- "%#0*.*f" : "%0*.*f");
-#endif
+ ((arg & FORM_NUM_POINT) ? "%#0*.*" NVff : "%0*.*" NVff);
goto ff_dec;
- case FF_DECIMAL:
+
+ case FF_DECIMAL: /* do @##, ^##, where <arg>=(precision|flags) */
arg = *fpc++;
-#if defined(USE_LONG_DOUBLE)
fmt = (const char *)
- ((arg & FORM_NUM_POINT) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl);
-#else
- fmt = (const char *)
- ((arg & FORM_NUM_POINT) ? "%#*.*f" : "%*.*f");
-#endif
+ ((arg & FORM_NUM_POINT) ? "%#*.*" NVff : "%*.*" NVff);
ff_dec:
/* If the field is marked with ^ and the value is undefined,
blank it out. */
}
/* Formats aren't yet marked for locales, so assume "yes". */
{
- STORE_NUMERIC_STANDARD_SET_LOCAL();
- arg &= ~(FORM_NUM_POINT|FORM_NUM_BLANK);
- my_snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg, value);
- RESTORE_NUMERIC_STANDARD();
+ Size_t max = SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget));
+ int len;
+ DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED();
+ arg &= ~(FORM_NUM_POINT|FORM_NUM_BLANK);
+#ifdef USE_QUADMATH
+ {
+ const char* qfmt = quadmath_format_single(fmt);
+ int len;
+ if (!qfmt)
+ Perl_croak_nocontext("panic: quadmath invalid format \"%s\"", fmt);
+ len = quadmath_snprintf(t, max, qfmt, (int) fieldsize, (int) arg, value);
+ if (len == -1)
+ Perl_croak_nocontext("panic: quadmath_snprintf failed, format \"%s\"", qfmt);
+ if (qfmt != fmt)
+ Safefree(fmt);
+ }
+#else
+ /* we generate fmt ourselves so it is safe */
+ GCC_DIAG_IGNORE(-Wformat-nonliteral);
+ len = my_snprintf(t, max, fmt, (int) fieldsize, (int) arg, value);
+ GCC_DIAG_RESTORE;
+#endif
+ PERL_MY_SNPRINTF_POST_GUARD(len, max);
+ RESTORE_LC_NUMERIC();
}
t += fieldsize;
break;
- case FF_NEWLINE:
+ case FF_NEWLINE: /* delete trailing spaces, then append \n */
f++;
while (t-- > (SvPVX(PL_formtarget) + linemark) && *t == ' ') ;
t++;
*t++ = '\n';
break;
- case FF_BLANK:
+ case FF_BLANK: /* for arg==0: do '~'; for arg>0 : do '~~' */
arg = *fpc++;
if (gotsome) {
if (arg) { /* repeat until fields exhausted? */
}
break;
- case FF_MORE:
+ case FF_MORE: /* replace long end of string with '...' */
{
const char *s = chophere;
const char *send = item + len;
}
break;
}
- case FF_END:
+
+ case FF_END: /* tidy up, then return */
end:
assert(t < SvPVX_const(PL_formtarget) + SvLEN(PL_formtarget));
*t = '\0';
PP(pp_grepstart)
{
- dVAR; dSP;
+ dSP;
SV *src;
if (PL_stack_base + *PL_markstack_ptr == SP) {
SAVEVPTR(PL_curpm);
src = PL_stack_base[*PL_markstack_ptr];
- if (SvPADTMP(src) && !IS_PADGV(src)) {
+ if (SvPADTMP(src)) {
src = PL_stack_base[*PL_markstack_ptr] = sv_mortalcopy(src);
PL_tmps_floor++;
}
PP(pp_mapwhile)
{
- dVAR; dSP;
+ dSP;
const I32 gimme = GIMME_V;
I32 items = (SP - PL_stack_base) - *PL_markstack_ptr; /* how many new items */
I32 count;
/* set $_ to the new source item */
src = PL_stack_base[PL_markstack_ptr[-1]];
- if (SvPADTMP(src) && !IS_PADGV(src)) src = sv_mortalcopy(src);
+ if (SvPADTMP(src)) {
+ src = sv_mortalcopy(src);
+ }
SvTEMP_off(src);
if (PL_op->op_private & OPpGREP_LEX)
PAD_SVl(PL_op->op_targ) = src;
PP(pp_range)
{
- dVAR;
- if (GIMME == G_ARRAY)
+ if (GIMME_V == G_ARRAY)
return NORMAL;
if (SvTRUEx(PAD_SV(PL_op->op_targ)))
return cLOGOP->op_other;
PP(pp_flip)
{
- dVAR;
dSP;
- if (GIMME == G_ARRAY) {
+ if (GIMME_V == G_ARRAY) {
RETURNOP(((LOGOP*)cUNOP->op_first)->op_other);
}
else {
PP(pp_flop)
{
- dVAR; dSP;
+ dSP;
- if (GIMME == G_ARRAY) {
+ if (GIMME_V == G_ARRAY) {
dPOPPOPssrl;
SvGETMAGIC(left);
SvGETMAGIC(right);
if (RANGE_IS_NUMERIC(left,right)) {
- IV i, j;
- IV max;
+ IV i, j, n;
if ((SvOK(left) && !SvIOK(left) && SvNV_nomg(left) < IV_MIN) ||
(SvOK(right) && (SvIOK(right)
? SvIsUV(right) && SvUV(right) > IV_MAX
: SvNV_nomg(right) > IV_MAX)))
DIE(aTHX_ "Range iterator outside integer range");
i = SvIV_nomg(left);
- max = SvIV_nomg(right);
- if (max >= i) {
- j = max - i + 1;
- if (j > SSize_t_MAX)
- Perl_croak(aTHX_ "Out of memory during list extend");
- EXTEND_MORTAL(j);
- EXTEND(SP, j);
+ j = SvIV_nomg(right);
+ if (j >= i) {
+ /* Dance carefully around signed max. */
+ bool overflow = (i <= 0 && j > SSize_t_MAX + i - 1);
+ if (!overflow) {
+ n = j - i + 1;
+ /* The wraparound of signed integers is undefined
+ * behavior, but here we aim for count >=1, and
+ * negative count is just wrong. */
+ if (n < 1)
+ overflow = TRUE;
+ }
+ if (overflow)
+ Perl_croak(aTHX_ "Out of memory during list extend");
+ EXTEND_MORTAL(n);
+ EXTEND(SP, n);
}
else
- j = 0;
- while (j--) {
- SV * const sv = sv_2mortal(newSViv(i++));
+ n = 0;
+ while (n--) {
+ SV * const sv = sv_2mortal(newSViv(i));
PUSHs(sv);
+ if (n) /* avoid incrementing above IV_MAX */
+ i++;
}
}
else {
STATIC I32
S_dopoptolabel(pTHX_ const char *label, STRLEN len, U32 flags)
{
- dVAR;
I32 i;
PERL_ARGS_ASSERT_DOPOPTOLABEL;
I32
Perl_dowantarray(pTHX)
{
- dVAR;
const I32 gimme = block_gimme();
return (gimme == G_VOID) ? G_SCALAR : gimme;
}
I32
Perl_block_gimme(pTHX)
{
- dVAR;
const I32 cxix = dopoptosub(cxstack_ix);
if (cxix < 0)
return G_VOID;
return G_ARRAY;
default:
Perl_croak(aTHX_ "panic: bad gimme: %d\n", cxstack[cxix].blk_gimme);
- assert(0); /* NOTREACHED */
- return 0;
}
+ NOT_REACHED; /* NOTREACHED */
}
I32
Perl_is_lvalue_sub(pTHX)
{
- dVAR;
const I32 cxix = dopoptosub(cxstack_ix);
assert(cxix >= 0); /* We should only be called from inside subs */
I32
Perl_was_lvalue_sub(pTHX)
{
- dVAR;
const I32 cxix = dopoptosub(cxstack_ix-1);
assert(cxix >= 0); /* We should only be called from inside subs */
STATIC I32
S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock)
{
- dVAR;
I32 i;
PERL_ARGS_ASSERT_DOPOPTOSUB_AT;
+#ifndef DEBUGGING
+ PERL_UNUSED_CONTEXT;
+#endif
for (i = startingblock; i >= 0; i--) {
const PERL_CONTEXT * const cx = &cxstk[i];
* code block. Hide this faked entry from the world. */
if (cx->cx_type & CXp_SUB_RE_FAKE)
continue;
+ /* FALLTHROUGH */
case CXt_EVAL:
case CXt_FORMAT:
DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i));
STATIC I32
S_dopoptoeval(pTHX_ I32 startingblock)
{
- dVAR;
I32 i;
for (i = startingblock; i >= 0; i--) {
const PERL_CONTEXT *cx = &cxstack[i];
STATIC I32
S_dopoptoloop(pTHX_ I32 startingblock)
{
- dVAR;
I32 i;
for (i = startingblock; i >= 0; i--) {
const PERL_CONTEXT * const cx = &cxstack[i];
STATIC I32
S_dopoptogiven(pTHX_ I32 startingblock)
{
- dVAR;
I32 i;
for (i = startingblock; i >= 0; i--) {
const PERL_CONTEXT *cx = &cxstack[i];
STATIC I32
S_dopoptowhen(pTHX_ I32 startingblock)
{
- dVAR;
I32 i;
for (i = startingblock; i >= 0; i--) {
const PERL_CONTEXT *cx = &cxstack[i];
void
Perl_dounwind(pTHX_ I32 cxix)
{
- dVAR;
I32 optype;
if (!PL_curstackinfo) /* can happen if die during thread cloning */
void
Perl_qerror(pTHX_ SV *err)
{
- dVAR;
-
PERL_ARGS_ASSERT_QERROR;
if (PL_in_eval) {
void
Perl_die_unwind(pTHX_ SV *msv)
{
- dVAR;
SV *exceptsv = sv_mortalcopy(msv);
U8 in_eval = PL_in_eval;
PERL_ARGS_ASSERT_DIE_UNWIND;
SV *namesv;
PERL_CONTEXT *cx;
SV **newsp;
+#ifdef DEBUGGING
COP *oldcop;
+#endif
JMPENV *restartjmpenv;
OP *restartop;
}
POPEVAL(cx);
namesv = cx->blk_eval.old_namesv;
+#ifdef DEBUGGING
oldcop = cx->blk_oldcop;
+#endif
restartjmpenv = cx->blk_eval.cur_top_env;
restartop = cx->blk_eval.retop;
LEAVE;
- /* LEAVE could clobber PL_curcop (see save_re_context())
- * XXX it might be better to find a way to avoid messing with
- * PL_curcop in save_re_context() instead, but this is a more
- * minimal fix --GSAR */
- PL_curcop = oldcop;
-
if (optype == OP_REQUIRE) {
+ assert (PL_curcop == oldcop);
(void)hv_store(GvHVn(PL_incgv),
SvPVX_const(namesv),
SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
PL_restartjmpenv = restartjmpenv;
PL_restartop = restartop;
JMPENV_JUMP(3);
- assert(0); /* NOTREACHED */
+ NOT_REACHED; /* NOTREACHED */
}
}
write_to_stderr(exceptsv);
my_failure_exit();
- assert(0); /* NOTREACHED */
+ NOT_REACHED; /* NOTREACHED */
}
PP(pp_xor)
{
- dVAR; dSP; dPOPTOPssrl;
+ dSP; dPOPTOPssrl;
if (SvTRUE(left) != SvTRUE(right))
RETSETYES;
else
}
/*
+
+=head1 CV Manipulation Functions
+
=for apidoc caller_cx
-The XSUB-writer's equivalent of L<caller()|perlfunc/caller>. The
+The XSUB-writer's equivalent of L<caller()|perlfunc/caller>. The
returned C<PERL_CONTEXT> structure can be interrogated to find all the
-information returned to Perl by C<caller>. Note that XSUBs don't get a
+information returned to Perl by C<caller>. Note that XSUBs don't get a
stack frame, so C<caller_cx(0, NULL)> will return information for the
immediately-surrounding Perl code.
This function skips over the automatic calls to C<&DB::sub> made on the
-behalf of the debugger. If the stack frame requested was a sub called by
+behalf of the debugger. If the stack frame requested was a sub called by
C<DB::sub>, the return value will be the frame for the call to
C<DB::sub>, since that has the correct line number/etc. for the call
-site. If I<dbcxp> is non-C<NULL>, it will be set to a pointer to the
+site. If I<dbcxp> is non-C<NULL>, it will be set to a pointer to the
frame for the sub call itself.
=cut
PP(pp_caller)
{
- dVAR;
dSP;
const PERL_CONTEXT *cx;
const PERL_CONTEXT *dbcx;
- I32 gimme;
+ I32 gimme = GIMME_V;
const HEK *stash_hek;
I32 count = 0;
bool has_arg = MAXARG && TOPs;
cx = caller_cx(count + !!(PL_op->op_private & OPpOFFBYONE), &dbcx);
if (!cx) {
- if (GIMME != G_ARRAY) {
+ if (gimme != G_ARRAY) {
EXTEND(SP, 1);
RETPUSHUNDEF;
}
stash_hek = SvTYPE(CopSTASH(cx->blk_oldcop)) == SVt_PVHV
? HvNAME_HEK((HV*)CopSTASH(cx->blk_oldcop))
: NULL;
- if (GIMME != G_ARRAY) {
+ if (gimme != G_ARRAY) {
EXTEND(SP, 1);
if (!stash_hek)
PUSHs(&PL_sv_undef);
PUSHTARG;
}
mPUSHs(newSVpv(OutCopFILE(cx->blk_oldcop), 0));
- lcop = closest_cop(cx->blk_oldcop, cx->blk_oldcop->op_sibling,
+ lcop = closest_cop(cx->blk_oldcop, OpSIBLING(cx->blk_oldcop),
cx->blk_sub.retop, TRUE);
if (!lcop)
lcop = cx->blk_oldcop;
if (!has_arg)
RETURN;
if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
- GV * const cvgv = CvGV(dbcx->blk_sub.cv);
/* So is ccstack[dbcxix]. */
- if (cvgv && isGV(cvgv)) {
- SV * const sv = newSV(0);
- gv_efullname3(sv, cvgv, NULL);
- mPUSHs(sv);
+ if (CvHASGV(dbcx->blk_sub.cv)) {
+ PUSHs(cv_name(dbcx->blk_sub.cv, 0, 0));
PUSHs(boolSV(CxHASARGS(cx)));
}
else {
if (CxTYPE(cx) == CXt_EVAL) {
/* eval STRING */
if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) {
- PUSHs(newSVpvn_flags(SvPVX(cx->blk_eval.cur_text),
- SvCUR(cx->blk_eval.cur_text)-2,
- SvUTF8(cx->blk_eval.cur_text)|SVs_TEMP));
+ SV *cur_text = cx->blk_eval.cur_text;
+ if (SvCUR(cur_text) >= 2) {
+ PUSHs(newSVpvn_flags(SvPVX(cur_text), SvCUR(cur_text)-2,
+ SvUTF8(cur_text)|SVs_TEMP));
+ }
+ else {
+ /* I think this is will always be "", but be sure */
+ PUSHs(sv_2mortal(newSVsv(cur_text)));
+ }
+
PUSHs(&PL_sv_no);
}
/* require */
PP(pp_reset)
{
- dVAR;
dSP;
const char * tmps;
STRLEN len = 0;
PP(pp_dbstate)
{
- dVAR;
PL_curcop = (COP*)PL_op;
TAINT_NOT; /* Each statement is presumed innocent */
PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
PERL_ASYNC_CHECK();
if (PL_op->op_flags & OPf_SPECIAL /* breakpoint */
- || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace))
+ || PL_DBsingle_iv || PL_DBsignal_iv || PL_DBtrace_iv)
{
dSP;
PERL_CONTEXT *cx;
return NORMAL;
}
+/* S_leave_common: Common code that many functions in this file use on
+ scope exit. */
+
+/* SVs on the stack that have any of the flags passed in are left as is.
+ Other SVs are protected via the mortals stack if lvalue is true, and
+ copied otherwise.
+
+ Also, taintedness is cleared.
+*/
+
STATIC SV **
-S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 flags)
+S_leave_common(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme,
+ U32 flags, bool lvalue)
{
bool padtmp = 0;
- PERL_ARGS_ASSERT_ADJUST_STACK_ON_LEAVE;
+ PERL_ARGS_ASSERT_LEAVE_COMMON;
+ TAINT_NOT;
if (flags & SVs_PADTMP) {
flags &= ~SVs_PADTMP;
padtmp = 1;
if (gimme == G_SCALAR) {
if (MARK < SP)
*++newsp = ((SvFLAGS(*SP) & flags) || (padtmp && SvPADTMP(*SP)))
- ? *SP : sv_mortalcopy(*SP);
+ ? *SP
+ : lvalue
+ ? sv_2mortal(SvREFCNT_inc_simple_NN(*SP))
+ : sv_mortalcopy(*SP);
else {
/* MEXTEND() only updates MARK, so reuse it instead of newsp. */
MARK = newsp;
if ((SvFLAGS(*MARK) & flags) || (padtmp && SvPADTMP(*MARK)))
*++newsp = *MARK;
else {
- *++newsp = sv_mortalcopy(*MARK);
+ *++newsp = lvalue
+ ? sv_2mortal(SvREFCNT_inc_simple_NN(*MARK))
+ : sv_mortalcopy(*MARK);
TAINT_NOT; /* Each item is independent */
}
}
PP(pp_enter)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
I32 gimme = GIMME_V;
PP(pp_leave)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
SV **newsp;
PMOP *newpm;
gimme = OP_GIMME(PL_op, (cxstack_ix >= 0) ? gimme : G_SCALAR);
- TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = leave_common(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP,
+ PL_op->op_private & OPpLVALUE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("block");
RETURN;
}
+static bool
+S_outside_integer(pTHX_ SV *sv)
+{
+ if (SvOK(sv)) {
+ const NV nv = SvNV_nomg(sv);
+ if (Perl_isinfnan(nv))
+ return TRUE;
+#ifdef NV_PRESERVES_UV
+ if (nv < (NV)IV_MIN || nv > (NV)IV_MAX)
+ return TRUE;
+#else
+ if (nv <= (NV)IV_MIN)
+ return TRUE;
+ if ((nv > 0) &&
+ ((nv > (NV)UV_MAX ||
+ SvUV_nomg(sv) > (UV)IV_MAX)))
+ return TRUE;
+#endif
+ }
+ return FALSE;
+}
+
PP(pp_enteriter)
{
- dVAR; dSP; dMARK;
+ dSP; dMARK;
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
void *itervar; /* location of the iteration variable */
itervar = &PAD_SVl(PL_op->op_targ);
#endif
}
- else { /* symbol table variable */
+ else if (LIKELY(isGV(TOPs))) { /* symbol table variable */
GV * const gv = MUTABLE_GV(POPs);
SV** svp = &GvSV(gv);
save_pushptrptr(gv, SvREFCNT_inc(*svp), SAVEt_GVSV);
*svp = newSV(0);
itervar = (void *)gv;
+ save_aliased_sv(gv);
+ }
+ else {
+ SV * const sv = POPs;
+ assert(SvTYPE(sv) == SVt_PVMG);
+ assert(SvMAGIC(sv));
+ assert(SvMAGIC(sv)->mg_type == PERL_MAGIC_lvref);
+ itervar = (void *)sv;
+ cxtype |= CXp_FOR_LVREF;
}
if (PL_op->op_private & OPpITER_DEF)
if (SvTYPE(maybe_ary) != SVt_PVAV) {
dPOPss;
SV * const right = maybe_ary;
+ if (UNLIKELY(cxtype & CXp_FOR_LVREF))
+ DIE(aTHX_ "Assigned value is not a reference");
SvGETMAGIC(sv);
SvGETMAGIC(right);
if (RANGE_IS_NUMERIC(sv,right)) {
/* Make sure that no-one re-orders cop.h and breaks our
assumptions */
assert(CxTYPE(cx) == CXt_LOOP_LAZYIV);
-#ifdef NV_PRESERVES_UV
- if ((SvOK(sv) && ((SvNV_nomg(sv) < (NV)IV_MIN) ||
- (SvNV_nomg(sv) > (NV)IV_MAX)))
- ||
- (SvOK(right) && ((SvNV_nomg(right) > (NV)IV_MAX) ||
- (SvNV_nomg(right) < (NV)IV_MIN))))
-#else
- if ((SvOK(sv) && ((SvNV_nomg(sv) <= (NV)IV_MIN)
- ||
- ((SvNV_nomg(sv) > 0) &&
- ((SvUV_nomg(sv) > (UV)IV_MAX) ||
- (SvNV_nomg(sv) > (NV)UV_MAX)))))
- ||
- (SvOK(right) && ((SvNV_nomg(right) <= (NV)IV_MIN)
- ||
- ((SvNV_nomg(right) > 0) &&
- ((SvUV_nomg(right) > (UV)IV_MAX) ||
- (SvNV_nomg(right) > (NV)UV_MAX))
- ))))
-#endif
+ if (S_outside_integer(aTHX_ sv) ||
+ S_outside_integer(aTHX_ right))
DIE(aTHX_ "Range iterator outside integer range");
cx->blk_loop.state_u.lazyiv.cur = SvIV_nomg(sv);
cx->blk_loop.state_u.lazyiv.end = SvIV_nomg(right);
PP(pp_enterloop)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
PP(pp_leaveloop)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
I32 gimme;
SV **newsp;
mark = newsp;
newsp = PL_stack_base + cx->blk_loop.resetsp;
- TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, MARK, gimme, 0);
+ SP = leave_common(newsp, SP, MARK, gimme, 0,
+ PL_op->op_private & OPpLVALUE);
PUTBACK;
POPLOOP(cx); /* Stack values are safe: release loop vars ... */
const char *what = NULL;
if (MARK < SP) {
assert(MARK+1 == SP);
- if ((SvPADTMP(TOPs) ||
- (SvFLAGS(TOPs) & (SVf_READONLY | SVf_FAKE))
- == SVf_READONLY
- ) &&
+ if ((SvPADTMP(TOPs) || SvREADONLY(TOPs)) &&
!SvSMAGICAL(TOPs)) {
what =
SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef"
: sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
else while (++MARK <= SP) {
if (*MARK != &PL_sv_undef
- && (SvPADTMP(*MARK)
- || (SvFLAGS(*MARK) & (SVf_READONLY|SVf_FAKE))
- == SVf_READONLY
- )
+ && (SvPADTMP(*MARK) || SvREADONLY(*MARK))
) {
+ const bool ro = cBOOL( SvREADONLY(*MARK) );
SV *sv;
/* Might be flattened array after $#array = */
PUTBACK;
/* diag_listed_as: Can't return %s from lvalue subroutine */
Perl_croak(aTHX_
"Can't return a %s from lvalue subroutine",
- SvREADONLY(TOPs) ? "readonly value" : "temporary");
+ ro ? "readonly value" : "temporary");
}
else
*++newsp =
PP(pp_return)
{
- dVAR; dSP; dMARK;
+ dSP; dMARK;
PERL_CONTEXT *cx;
bool popsub2 = FALSE;
bool clear_errsv = FALSE;
* pp_return */
PP(pp_leavesublv)
{
- dVAR; dSP;
+ dSP;
SV **newsp;
PMOP *newpm;
I32 gimme;
static I32
S_unwind_loop(pTHX_ const char * const opname)
{
- dVAR;
I32 cxix;
if (PL_op->op_flags & OPf_SPECIAL) {
cxix = dopoptoloop(cxstack_ix);
PP(pp_last)
{
- dVAR;
PERL_CONTEXT *cx;
I32 pop2 = 0;
I32 gimme;
OP *nextop = NULL;
SV **newsp;
PMOP *newpm;
- SV **mark;
SV *sv = NULL;
S_unwind_loop(aTHX_ "last");
POPBLOCK(cx,newpm);
cxstack_ix++; /* temporarily protect top context */
- mark = newsp;
switch (CxTYPE(cx)) {
case CXt_LOOP_LAZYIV:
case CXt_LOOP_LAZYSV:
}
TAINT_NOT;
- PL_stack_sp = adjust_stack_on_leave(newsp, PL_stack_sp, MARK, gimme,
- pop2 == CXt_SUB ? SVs_TEMP : 0);
+ PL_stack_sp = newsp;
LEAVE;
cxstack_ix--;
PP(pp_next)
{
- dVAR;
PERL_CONTEXT *cx;
const I32 inner = PL_scopestack_ix;
PP(pp_redo)
{
- dVAR;
const I32 cxix = S_unwind_loop(aTHX_ "redo");
PERL_CONTEXT *cx;
I32 oldsave;
STATIC OP *
S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstack, OP **oplimit)
{
- dVAR;
OP **ops = opstack;
static const char* const too_deep = "Target of goto is too deeply nested";
if (o->op_flags & OPf_KIDS) {
OP *kid;
/* First try all the kids at this level, since that's likeliest. */
- for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) {
+ for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
STRLEN kid_label_len;
U32 kid_label_flags;
return kid;
}
}
- for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) {
+ for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
if (kid == PL_lastgotoprobe)
continue;
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
return 0;
}
-PP(pp_goto) /* also pp_dump */
+
+/* also used for: pp_dump() */
+
+PP(pp_goto)
{
dVAR; dSP;
OP *retop = NULL;
SAVETMPS;
SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */
if (CvISXSUB(cv)) {
- OP* const retop = cx->blk_sub.retop;
SV **newsp;
I32 gimme;
- const SSize_t items = arg ? AvFILLp(arg) + 1 : 0;
+ const SSize_t items = arg ? AvFILL(arg) + 1 : 0;
+ const bool m = arg ? cBOOL(SvRMAGICAL(arg)) : 0;
SV** mark;
PERL_UNUSED_VAR(newsp);
/* put GvAV(defgv) back onto stack */
if (items) {
EXTEND(SP, items+1); /* @_ could have been extended. */
- Copy(AvARRAY(arg), SP + 1, items, SV*);
}
mark = SP;
- SP += items;
- if (items && AvREAL(arg)) {
- I32 index;
+ if (items) {
+ SSize_t index;
+ bool r = cBOOL(AvREAL(arg));
for (index=0; index<items; index++)
- if (SP[-index])
- SvREFCNT_inc_void_NN(sv_2mortal(SP[-index]));
- else {
- SP[-index] = sv_2mortal(newSVavdefelem(arg,
- AvFILLp(arg) - index, 1));
+ {
+ SV *sv;
+ if (m) {
+ SV ** const svp = av_fetch(arg, index, 0);
+ sv = svp ? *svp : NULL;
}
+ else sv = AvARRAY(arg)[index];
+ SP[index+1] = sv
+ ? r ? SvREFCNT_inc_NN(sv_2mortal(sv)) : sv
+ : sv_2mortal(newSVavdefelem(arg, index, 1));
+ }
}
+ SP += items;
SvREFCNT_dec(arg);
if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) {
/* Restore old @_ */
SvREFCNT_dec(arg);
}
+ retop = cx->blk_sub.retop;
/* XS subs don't have a CxSUB, so pop it */
POPBLOCK(cx, PL_curpm);
/* Push a mark for the start of arglist */
PUTBACK;
(void)(*CvXSUB(cv))(aTHX_ cv);
LEAVE;
- PERL_ASYNC_CHECK();
- return retop;
+ goto _return;
}
else {
PADLIST * const padlist = CvPADLIST(cv);
to freed memory as the result of undef *_. So put
it in the callee’s pad, donating our refer-
ence count. */
- SvREFCNT_dec(PAD_SVl(0));
- PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg);
+ if (arg) {
+ SvREFCNT_dec(PAD_SVl(0));
+ PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg);
+ }
/* GvAV(PL_defgv) might have been modified on scope
exit, so restore it. */
}
}
}
- PERL_ASYNC_CHECK();
- RETURNOP(CvSTART(cv));
+ retop = CvSTART(cv);
+ goto putback_return;
}
}
else {
case CXt_LOOP_PLAIN:
case CXt_GIVEN:
case CXt_WHEN:
- gotoprobe = cx->blk_oldcop->op_sibling;
+ gotoprobe = OpSIBLING(cx->blk_oldcop);
break;
case CXt_SUBST:
continue;
case CXt_BLOCK:
if (ix) {
- gotoprobe = cx->blk_oldcop->op_sibling;
+ gotoprobe = OpSIBLING(cx->blk_oldcop);
in_block = TRUE;
} else
gotoprobe = PL_main_root;
gotoprobe = CvROOT(cx->blk_sub.cv);
break;
}
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case CXt_FORMAT:
case CXt_NULL:
DIE(aTHX_ "Can't \"goto\" out of a pseudo block");
break;
}
if (gotoprobe) {
+ OP *sibl1, *sibl2;
+
retop = dofindlabel(gotoprobe, label, label_len, label_flags,
enterops, enterops + GOTO_DEPTH);
if (retop)
break;
- if (gotoprobe->op_sibling &&
- gotoprobe->op_sibling->op_type == OP_UNSTACK &&
- gotoprobe->op_sibling->op_sibling) {
- retop = dofindlabel(gotoprobe->op_sibling->op_sibling,
+ if ( (sibl1 = OpSIBLING(gotoprobe)) &&
+ sibl1->op_type == OP_UNSTACK &&
+ (sibl2 = OpSIBLING(sibl1)))
+ {
+ retop = dofindlabel(sibl2,
label, label_len, label_flags, enterops,
enterops + GOTO_DEPTH);
if (retop)
I32 oldsave;
if (ix < 0)
- ix = 0;
+ DIE(aTHX_ "panic: docatch: illegal ix=%ld", (long)ix);
dounwind(ix);
TOPBLOCK(cx);
oldsave = PL_scopestack[PL_scopestack_ix];
PL_do_undump = FALSE;
}
+ putback_return:
+ PL_stack_sp = sp;
+ _return:
PERL_ASYNC_CHECK();
- RETURNOP(retop);
+ return retop;
}
PP(pp_exit)
{
- dVAR;
dSP;
I32 anum;
else {
anum = SvIVx(POPs);
#ifdef VMS
- if (anum == 1 && (PL_op->op_private & OPpEXIT_VMSISH))
+ if (anum == 1
+ && SvTRUE(cop_hints_fetch_pvs(PL_curcop, "vmsish_exit", 0)))
anum = 0;
- VMSISH_HUSHED = VMSISH_HUSHED || (PL_op->op_private & OPpHUSH_VMSISH);
+ VMSISH_HUSHED =
+ VMSISH_HUSHED || (PL_curcop->op_private & OPpHUSH_VMSISH);
#endif
}
PL_exit_flags |= PERL_EXIT_EXPECTED;
-#ifdef PERL_MAD
- /* KLUDGE: disable exit 0 in BEGIN blocks when we're just compiling */
- if (anum || !(PL_minus_c && PL_madskills))
- my_exit(anum);
-#else
my_exit(anum);
-#endif
PUSHs(&PL_sv_undef);
RETURN;
}
STATIC OP *
S_docatch(pTHX_ OP *o)
{
- dVAR;
int ret;
OP * const oldop = PL_op;
dJMPENV;
PL_restartop = 0;
goto redo_body;
}
- /* FALL THROUGH */
+ /* FALLTHROUGH */
default:
JMPENV_POP;
PL_op = oldop;
JMPENV_JUMP(ret);
- assert(0); /* NOTREACHED */
+ NOT_REACHED; /* NOTREACHED */
}
JMPENV_POP;
PL_op = oldop;
Locate the CV corresponding to the currently executing sub or eval.
If db_seqp is non_null, skip CVs that are in the DB package and populate
*db_seqp with the cop sequence number at the point that the DB:: code was
-entered. (allows debuggers to eval in the scope of the breakpoint rather
-than in the scope of the debugger itself).
+entered. (This allows debuggers to eval in the scope of the breakpoint
+rather than in the scope of the debugger itself.)
=cut
*/
CV *
Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp)
{
- dVAR;
PERL_SI *si;
int level = 0;
switch (cond) {
case FIND_RUNCV_padid_eq:
if (!CvPADLIST(cv)
- || PadlistNAMES(CvPADLIST(cv)) != INT2PTR(PADNAMELIST *, arg))
+ || CvPADLIST(cv)->xpadl_id != (U32)arg)
continue;
return cv;
case FIND_RUNCV_level_eq:
default:
JMPENV_POP;
JMPENV_JUMP(ret);
- assert(0); /* NOTREACHED */
+ NOT_REACHED; /* NOTREACHED */
}
JMPENV_POP;
return ret;
STATIC bool
S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
{
- dVAR; dSP;
+ dSP;
OP * const saveop = PL_op;
bool clear_hints = saveop->op_type != OP_ENTEREVAL;
COP * const oldcurcop = PL_curcop;
/* set up a scratch pad */
- CvPADLIST(evalcv) = pad_new(padnew_SAVE);
+ CvPADLIST_set(evalcv, pad_new(padnew_SAVE));
PL_op = NULL; /* avoid PL_op and PL_curpad referring to different CVs */
- if (!PL_madskills)
- SAVEMORTALIZESV(evalcv); /* must remain until end of current statement */
+ SAVEMORTALIZESV(evalcv); /* must remain until end of current statement */
/* make sure we compile in the right package */
PL_unitcheckav = newAV();
SAVEFREESV(PL_unitcheckav);
-#ifdef PERL_MAD
- SAVEBOOL(PL_madskills);
- PL_madskills = 0;
-#endif
ENTER_with_name("evalcomp");
SAVESPTR(PL_compcv);
S_check_type_and_open(pTHX_ SV *name)
{
Stat_t st;
- const char *p = SvPV_nolen_const(name);
+ STRLEN len;
+ PerlIO * retio;
+ const char *p = SvPV_const(name, len);
int st_rc;
PERL_ARGS_ASSERT_CHECK_TYPE_AND_OPEN;
* rather than for the .pm file.
* This check prevents a \0 in @INC causing problems.
*/
- if (!IS_SAFE_PATHNAME(name, "require"))
+ if (!IS_SAFE_PATHNAME(p, len, "require"))
return NULL;
+ /* on Win32 stat is expensive (it does an open() and close() twice and
+ a couple other IO calls), the open will fail with a dir on its own with
+ errno EACCES, so only do a stat to separate a dir from a real EACCES
+ caused by user perms */
+#ifndef WIN32
+ /* we use the value of errno later to see how stat() or open() failed.
+ * We don't want it set if the stat succeeded but we still failed,
+ * such as if the name exists, but is a directory */
+ errno = 0;
+
st_rc = PerlLIO_stat(p, &st);
if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
return NULL;
}
+#endif
-#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
- return PerlIO_openn(aTHX_ ":", PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
+#if !defined(PERLIO_IS_STDIO)
+ retio = PerlIO_openn(aTHX_ ":", PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
#else
- return PerlIO_open(p, PERL_SCRIPT_MODE);
+ retio = PerlIO_open(p, PERL_SCRIPT_MODE);
+#endif
+#ifdef WIN32
+ /* EACCES stops the INC search early in pp_require to implement
+ feature RT #113422 */
+ if(!retio && errno == EACCES) { /* exists but probably a directory */
+ int eno;
+ st_rc = PerlLIO_stat(p, &st);
+ if (st_rc >= 0) {
+ if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
+ eno = 0;
+ else
+ eno = EACCES;
+ errno = eno;
+ }
+ }
#endif
+ return retio;
}
#ifndef PERL_DISABLE_PMC
* warning referring to the .pmc which the user probably doesn't
* know or care about
*/
- if (!IS_SAFE_PATHNAME(name, "require"))
+ if (!IS_SAFE_PATHNAME(p, namelen, "require"))
return NULL;
if (namelen > 3 && memEQs(p + namelen - 3, 3, ".pm")) {
Stat_t pmcstat;
SvSetSV_nosteal(pmcsv,name);
- sv_catpvn(pmcsv, "c", 1);
+ sv_catpvs(pmcsv, "c");
if (PerlLIO_stat(SvPV_nolen_const(pmcsv), &pmcstat) >= 0)
return check_type_and_open(pmcsv);
#endif /* !PERL_DISABLE_PMC */
/* require doesn't search for absolute names, or when the name is
- explicity relative the current directory */
+ explicitly relative the current directory */
PERL_STATIC_INLINE bool
S_path_is_searchable(const char *name)
{
return TRUE;
}
+
+/* also used for: pp_dofile() */
+
PP(pp_require)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
SV *sv;
const char *name;
STRLEN unixlen;
#ifdef VMS
int vms_unixname = 0;
- char *unixnamebuf;
char *unixdir;
- char *unixdirbuf;
#endif
const char *tryname = NULL;
SV *namesv = NULL;
SV *filter_state = NULL;
SV *filter_sub = NULL;
SV *hook_sv = NULL;
- SV *encoding;
OP *op;
int saved_errno;
bool path_searchable;
sv = POPs;
+ SvGETMAGIC(sv);
if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) {
sv = sv_2mortal(new_version(sv));
if (!Perl_sv_derived_from_pvn(aTHX_ PL_patchlevel, STR_WITH_LEN("version"), 0))
first = SvIV(*av_fetch(lav,0,0));
if ( first > (int)PERL_REVISION /* probably 'use 6.0' */
|| hv_exists(MUTABLE_HV(req), "qv", 2 ) /* qv style */
- || av_len(lav) > 1 /* FP with > 3 digits */
+ || av_tindex(lav) > 1 /* FP with > 3 digits */
|| strstr(SvPVX(pv),".0") /* FP with leading 0 */
) {
DIE(aTHX_ "Perl %"SVf" required--this is only "
SV *hintsv;
I32 second = 0;
- if (av_len(lav)>=1)
+ if (av_tindex(lav)>=1)
second = SvIV(*av_fetch(lav,1,0));
second /= second >= 600 ? 100 : 10;
RETPUSHYES;
}
- name = SvPV_const(sv, len);
+ if (!SvOK(sv))
+ DIE(aTHX_ "Missing or undefined argument to require");
+ name = SvPV_nomg_const(sv, len);
if (!(name && len > 0 && *name))
- DIE(aTHX_ "Null filename used");
- if (!IS_SAFE_PATHNAME(sv, "require")) {
+ DIE(aTHX_ "Missing or undefined argument to require");
+
+ if (!IS_SAFE_PATHNAME(name, len, "require")) {
DIE(aTHX_ "Can't locate %s: %s",
pv_escape(newSVpvs_flags("",SVs_TEMP),SvPVX(sv),SvCUR(sv),
SvCUR(sv)*2,NULL, SvUTF8(sv)?PERL_PV_ESCAPE_UNI:0),
* name can be translated to UNIX.
*/
- if ((unixnamebuf = SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1))))
- && (unixname = tounixspec(name, unixnamebuf)) != NULL) {
+ if ((unixname =
+ tounixspec(name, SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1)))))
+ != NULL) {
unixlen = strlen(unixname);
vms_unixname = 1;
}
if (vms_unixname)
#endif
{
+ SV *nsv = sv;
namesv = newSV_type(SVt_PV);
for (i = 0; i <= AvFILL(ar); i++) {
SV * const dirsv = *av_fetch(ar, i, TRUE);
- if (SvTIED_mg((const SV *)ar, PERL_MAGIC_tied))
- mg_get(dirsv);
+ SvGETMAGIC(dirsv);
if (SvROK(dirsv)) {
int count;
SV **svp;
SV *loader = dirsv;
if (SvTYPE(SvRV(loader)) == SVt_PVAV
- && !sv_isobject(loader))
+ && !SvOBJECT(SvRV(loader)))
{
loader = *av_fetch(MUTABLE_AV(SvRV(loader)), 0, TRUE);
+ SvGETMAGIC(loader);
}
Perl_sv_setpvf(aTHX_ namesv, "/loader/0x%"UVxf"/%s",
tryname = SvPVX_const(namesv);
tryrsfp = NULL;
+ if (SvPADTMP(nsv)) {
+ nsv = sv_newmortal();
+ SvSetSV_nosteal(nsv,sv);
+ }
+
ENTER_with_name("call_INC");
SAVETMPS;
EXTEND(SP, 2);
PUSHMARK(SP);
PUSHs(dirsv);
- PUSHs(sv);
+ PUSHs(nsv);
PUTBACK;
+ if (SvGMAGICAL(loader)) {
+ SV *l = sv_newmortal();
+ sv_setsv_nomg(l, loader);
+ loader = l;
+ }
if (sv_isobject(loader))
count = call_method("INC", G_ARRAY);
else
SP--;
}
+ /* FREETMPS may free our filter_cache */
+ SvREFCNT_inc_simple_void(filter_cache);
+
PUTBACK;
FREETMPS;
LEAVE_with_name("call_INC");
+ /* Now re-mortalize it. */
+ sv_2mortal(filter_cache);
+
/* Adjust file name if the hook has set an %INC entry.
This needs to happen after the FREETMPS above. */
svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
filter_has_file = 0;
filter_cache = NULL;
if (filter_state) {
- SvREFCNT_dec(filter_state);
+ SvREFCNT_dec_NN(filter_state);
filter_state = NULL;
}
if (filter_sub) {
- SvREFCNT_dec(filter_sub);
+ SvREFCNT_dec_NN(filter_sub);
filter_sub = NULL;
}
}
STRLEN dirlen;
if (SvOK(dirsv)) {
- dir = SvPV_const(dirsv, dirlen);
+ dir = SvPV_nomg_const(dirsv, dirlen);
} else {
dir = "";
dirlen = 0;
}
+ if (!IS_SAFE_SYSCALL(dir, dirlen, "@INC entry", "require"))
+ continue;
#ifdef VMS
- if (((unixdirbuf = SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1)))) == NULL)
- || ((unixdir = tounixpath(dir, unixdirbuf)) == NULL))
+ if ((unixdir =
+ tounixpath(dir, SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1)))))
+ == NULL)
continue;
sv_setpv(namesv, unixdir);
sv_catpv(namesv, unixname);
/* Avoid '<dir>//<file>' */
if (!dirlen || *(tmp-1) != '/') {
*tmp++ = '/';
+ } else {
+ /* So SvCUR_set reports the correct length below */
+ dirlen--;
}
/* name came from an SV, so it will have a '\0' at the
if (PL_op->op_type == OP_REQUIRE) {
if(saved_errno == EMFILE || saved_errno == EACCES) {
/* diag_listed_as: Can't locate %s */
- DIE(aTHX_ "Can't locate %s: %s", name, Strerror(saved_errno));
+ DIE(aTHX_ "Can't locate %s: %s: %s",
+ name, tryname, Strerror(saved_errno));
} else {
if (namesv) { /* did we lookup @INC? */
AV * const ar = GvAVn(PL_incgv);
sv_catpv(msg, " (you may need to install the ");
for (c = name; c < e; c++) {
if (*c == '/') {
- sv_catpvn(msg, "::", 2);
+ sv_catpvs(msg, "::");
}
else {
sv_catpvn(msg, c, 1);
PUTBACK;
- /* Store and reset encoding. */
- encoding = PL_encoding;
- PL_encoding = NULL;
-
if (doeval(gimme, NULL, PL_curcop->cop_seq, NULL))
op = DOCATCH(PL_eval_start);
else
op = PL_op->op_next;
- /* Restore encoding. */
- PL_encoding = encoding;
-
LOADED_FILE_PROBE(unixname);
return op;
PP(pp_hintseval)
{
- dVAR;
dSP;
mXPUSHs(MUTABLE_SV(hv_copy_hints_hv(MUTABLE_HV(cSVOP_sv))));
RETURN;
PP(pp_entereval)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
SV *sv;
const I32 gimme = GIMME_V;
PP(pp_leaveeval)
{
- dVAR; dSP;
+ dSP;
SV **newsp;
PMOP *newpm;
I32 gimme;
retop = cx->blk_eval.retop;
evalcv = cx->blk_eval.cv;
- TAINT_NOT;
- SP = adjust_stack_on_leave((gimme == G_VOID) ? SP : newsp, SP, newsp,
- gimme, SVs_TEMP);
+ SP = leave_common((gimme == G_VOID) ? SP : newsp, SP, newsp,
+ gimme, SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
#ifdef DEBUGGING
SvPVX_const(namesv),
SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
G_DISCARD);
- retop = Perl_die(aTHX_ "%"SVf" did not return a true value",
- SVfARG(namesv));
+ Perl_die(aTHX_ "%"SVf" did not return a true value", SVfARG(namesv));
+ NOT_REACHED; /* NOTREACHED */
/* die_unwind() did LEAVE, or we won't be here */
}
else {
PP(pp_entertry)
{
- dVAR;
PERL_CONTEXT * const cx = create_eval_scope(0);
cx->blk_eval.retop = cLOGOP->op_other->op_next;
return DOCATCH(PL_op->op_next);
PP(pp_leavetry)
{
- dVAR; dSP;
+ dSP;
SV **newsp;
PMOP *newpm;
I32 gimme;
POPEVAL(cx);
PERL_UNUSED_VAR(optype);
- TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = leave_common(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("eval_scope");
PP(pp_entergiven)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
PP(pp_leavegiven)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
I32 gimme;
SV **newsp;
POPBLOCK(cx,newpm);
assert(CxTYPE(cx) == CXt_GIVEN);
- TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = leave_common(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("given");
STATIC PMOP *
S_make_matcher(pTHX_ REGEXP *re)
{
- dVAR;
PMOP *matcher = (PMOP *) newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED);
PERL_ARGS_ASSERT_MAKE_MATCHER;
STATIC bool
S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv)
{
- dVAR;
dSP;
PERL_ARGS_ASSERT_MATCHER_MATCHES_SV;
STATIC void
S_destroy_matcher(pTHX_ PMOP *matcher)
{
- dVAR;
-
PERL_ARGS_ASSERT_DESTROY_MATCHER;
PERL_UNUSED_ARG(matcher);
STATIC OP *
S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
{
- dVAR;
dSP;
bool object_on_left = FALSE;
SSize_t i;
bool andedresults = TRUE;
AV *av = (AV*) SvRV(d);
- const I32 len = av_len(av);
+ const I32 len = av_tindex(av);
DEBUG_M(Perl_deb(aTHX_ " applying rule Array-CodeRef\n"));
if (len == -1)
RETPUSHYES;
/* Check that the key-sets are identical */
HE *he;
HV *other_hv = MUTABLE_HV(SvRV(d));
- bool tied = FALSE;
- bool other_tied = FALSE;
+ bool tied;
+ bool other_tied;
U32 this_key_count = 0,
other_key_count = 0;
HV *hv = MUTABLE_HV(SvRV(e));
DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Hash\n"));
/* Tied hashes don't know how many keys they have. */
- if (SvTIED_mg((SV*)hv, PERL_MAGIC_tied)) {
- tied = TRUE;
- }
- else if (SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied)) {
- HV * const temp = other_hv;
- other_hv = hv;
- hv = temp;
- tied = TRUE;
+ tied = cBOOL(SvTIED_mg((SV*)hv, PERL_MAGIC_tied));
+ other_tied = cBOOL(SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied));
+ if (!tied ) {
+ if(other_tied) {
+ /* swap HV sides */
+ HV * const temp = other_hv;
+ other_hv = hv;
+ hv = temp;
+ tied = TRUE;
+ other_tied = FALSE;
+ }
+ else if(HvUSEDKEYS((const HV *) hv) != HvUSEDKEYS(other_hv))
+ RETPUSHNO;
}
- if (SvTIED_mg((const SV *)other_hv, PERL_MAGIC_tied))
- other_tied = TRUE;
-
- if (!tied && HvUSEDKEYS((const HV *) hv) != HvUSEDKEYS(other_hv))
- RETPUSHNO;
/* The hashes have the same number of keys, so it suffices
to check that one is a subset of the other. */
}
else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
AV * const other_av = MUTABLE_AV(SvRV(d));
- const SSize_t other_len = av_len(other_av) + 1;
+ const SSize_t other_len = av_tindex(other_av) + 1;
SSize_t i;
HV *hv = MUTABLE_HV(SvRV(e));
}
else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
AV * const other_av = MUTABLE_AV(SvRV(e));
- const SSize_t other_len = av_len(other_av) + 1;
+ const SSize_t other_len = av_tindex(other_av) + 1;
SSize_t i;
DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Array\n"));
if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
AV *other_av = MUTABLE_AV(SvRV(d));
DEBUG_M(Perl_deb(aTHX_ " applying rule Array-Array\n"));
- if (av_len(MUTABLE_AV(SvRV(e))) != av_len(other_av))
+ if (av_tindex(MUTABLE_AV(SvRV(e))) != av_tindex(other_av))
RETPUSHNO;
else {
SSize_t i;
- const SSize_t other_len = av_len(other_av);
+ const SSize_t other_len = av_tindex(other_av);
if (NULL == seen_this) {
seen_this = newHV();
sm_regex_array:
{
PMOP * const matcher = make_matcher((REGEXP*) SvRV(d));
- const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
+ const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
SSize_t i;
for(i = 0; i <= this_len; ++i) {
}
else if (!SvOK(d)) {
/* undef ~~ array */
- const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
+ const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
SSize_t i;
DEBUG_M(Perl_deb(aTHX_ " applying rule Undef-Array\n"));
sm_any_array:
{
SSize_t i;
- const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
+ const SSize_t this_len = av_tindex(MUTABLE_AV(SvRV(e)));
DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Array\n"));
for (i = 0; i <= this_len; ++i) {
PP(pp_enterwhen)
{
- dVAR; dSP;
+ dSP;
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
PP(pp_leavewhen)
{
- dVAR; dSP;
+ dSP;
I32 cxix;
PERL_CONTEXT *cx;
I32 gimme;
POPBLOCK(cx,newpm);
assert(CxTYPE(cx) == CXt_WHEN);
- TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = leave_common(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* pop $1 et al */
LEAVE_with_name("when");
PP(pp_continue)
{
- dVAR; dSP;
+ dSP;
I32 cxix;
PERL_CONTEXT *cx;
I32 gimme;
PP(pp_break)
{
- dVAR;
I32 cxix;
PERL_CONTEXT *cx;
s++;
}
noblank = TRUE;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case ' ': case '\t':
skipspaces++;
continue;
static I32
S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
{
- dVAR;
SV * const datasv = FILTER_DATA(idx);
const int filter_has_file = IoLINES(datasv);
SV * const filter_state = MUTABLE_SV(IoTOP_GV(datasv));
umaxlen = maxlen;
/* I was having segfault trouble under Linux 2.2.5 after a
- parse error occured. (Had to hack around it with a test
+ parse error occurred. (Had to hack around it with a test
for PL_parser->error_count == 0.) Solaris doesn't segfault --
not sure where the trouble is yet. XXX */