static I32 sortcv _((SV *a, SV *b));
static void qsortsv _((SV **array, size_t num_elts, I32 (*fun)(SV *a, SV *b)));
static OP *doeval _((int gimme, OP** startop));
+static I32 amagic_cmp _((SV *str1, SV *str2));
+static I32 amagic_cmp_locale _((SV *str1, SV *str2));
#endif
PP(pp_wantarray)
double value;
bool gotsome;
STRLEN len;
+ STRLEN fudge = SvCUR(tmpForm) * (IN_UTF8 ? 3 : 1) + 1;
if (!SvMAGICAL(tmpForm) || !SvCOMPILED(tmpForm)) {
SvREADONLY_off(tmpForm);
}
SvPV_force(PL_formtarget, len);
- t = SvGROW(PL_formtarget, len + SvCUR(tmpForm) + 1); /* XXX SvCUR bad */
+ t = SvGROW(PL_formtarget, len + fudge + 1); /* XXX SvCUR bad */
t += len;
f = SvPV(tmpForm, len);
/* need to jump to the next word */
sv = *++MARK;
else {
sv = &PL_sv_no;
- if (PL_dowarn)
- warn("Not enough format arguments");
+ if (ckWARN(WARN_SYNTAX))
+ warner(WARN_SYNTAX, "Not enough format arguments");
}
break;
case FF_CHECKNL:
item = s = SvPV(sv, len);
itemsize = len;
+ if (IN_UTF8) {
+ itemsize = sv_len_utf8(sv);
+ if (itemsize != 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 (*s & ~31)
+ gotsome = TRUE;
+ else if (*s == '\n')
+ break;
+ s++;
+ }
+ itemsize = s - item;
+ sv_pos_b2u(sv, &itemsize);
+ break;
+ }
+ }
if (itemsize > fieldsize)
itemsize = fieldsize;
send = chophere = s + itemsize;
case FF_CHECKCHOP:
item = s = SvPV(sv, len);
itemsize = len;
+ if (IN_UTF8) {
+ itemsize = sv_len_utf8(sv);
+ if (itemsize != len) {
+ I32 itembytes;
+ if (itemsize <= fieldsize) {
+ send = chophere = s + itemsize;
+ while (s < send) {
+ if (*s == '\r') {
+ itemsize = s - item;
+ break;
+ }
+ if (*s++ & ~31)
+ gotsome = TRUE;
+ }
+ }
+ else {
+ 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 (*s & ~31)
+ gotsome = TRUE;
+ if (strchr(PL_chopset, *s))
+ chophere = s + 1;
+ }
+ s++;
+ }
+ itemsize = chophere - item;
+ sv_pos_b2u(sv, &itemsize);
+ }
+ break;
+ }
+ }
if (itemsize <= fieldsize) {
send = chophere = s + itemsize;
while (s < send) {
case FF_ITEM:
arg = itemsize;
s = item;
+ if (IN_UTF8) {
+ while (arg--) {
+ if (*s & 0x80) {
+ switch (UTF8SKIP(s)) {
+ case 7: *t++ = *s++;
+ case 6: *t++ = *s++;
+ case 5: *t++ = *s++;
+ case 4: *t++ = *s++;
+ case 3: *t++ = *s++;
+ case 2: *t++ = *s++;
+ case 1: *t++ = *s++;
+ }
+ }
+ else {
+ if ( !((*t++ = *s++) & ~31) )
+ t[-1] = ' ';
+ }
+ }
+ break;
+ }
while (arg--) {
#ifdef EBCDIC
int ch = *t++ = *s++;
}
SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget));
sv_catpvn(PL_formtarget, item, itemsize);
- SvGROW(PL_formtarget, SvCUR(PL_formtarget) + SvCUR(tmpForm) + 1);
+ SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1);
t = SvPVX(PL_formtarget) + SvCUR(PL_formtarget);
}
break;
}
}
+#define tryCALL_AMAGICbin(left,right,meth,svp) STMT_START { \
+ *svp = Nullsv; \
+ if (PL_amagic_generation) { \
+ if (SvAMAGIC(left)||SvAMAGIC(right))\
+ *svp = amagic_call(left, \
+ right, \
+ CAT2(meth,_amg), \
+ 0); \
+ } \
+ } STMT_END
+
+STATIC I32
+amagic_cmp(register SV *str1, register SV *str2)
+{
+ SV *tmpsv;
+ tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
+ if (tmpsv) {
+ double d;
+
+ if (SvIOK(tmpsv)) {
+ I32 i = SvIVX(tmpsv);
+ if (i > 0)
+ return 1;
+ return i? -1 : 0;
+ }
+ d = SvNV(tmpsv);
+ if (d > 0)
+ return 1;
+ return d? -1 : 0;
+ }
+ return sv_cmp(str1, str2);
+}
+
+STATIC I32
+amagic_cmp_locale(register SV *str1, register SV *str2)
+{
+ SV *tmpsv;
+ tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
+ if (tmpsv) {
+ double d;
+
+ if (SvIOK(tmpsv)) {
+ I32 i = SvIVX(tmpsv);
+ if (i > 0)
+ return 1;
+ return i? -1 : 0;
+ }
+ d = SvNV(tmpsv);
+ if (d > 0)
+ return 1;
+ return d? -1 : 0;
+ }
+ return sv_cmp_locale(str1, str2);
+}
+
PP(pp_sort)
{
djSP; dMARK; dORIGMARK;
CV *cv;
I32 gimme = GIMME;
OP* nextop = PL_op->op_next;
+ I32 overloading = 0;
if (gimme != G_ARRAY) {
SP = MARK;
}
PL_sortcop = CvSTART(cv);
SAVESPTR(CvROOT(cv)->op_ppaddr);
- CvROOT(cv)->op_ppaddr = ppaddr[OP_NULL];
+ CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];
SAVESPTR(PL_curpad);
PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
/*SUPPRESS 560*/
if (*up = *++MARK) { /* Weed out nulls. */
SvTEMP_off(*up);
- if (!PL_sortcop && !SvPOK(*up))
- (void)sv_2pv(*up, &PL_na);
+ if (!PL_sortcop && !SvPOK(*up)) {
+ if (SvAMAGIC(*up))
+ overloading = 1;
+ else
+ (void)sv_2pv(*up, &PL_na);
+ }
up++;
}
}
MEXTEND(SP, 20); /* Can't afford stack realloc on signal. */
qsortsv(ORIGMARK+1, max,
(PL_op->op_private & OPpLOCALE)
- ? FUNC_NAME_TO_PTR(sv_cmp_locale)
- : FUNC_NAME_TO_PTR(sv_cmp));
+ ? ( overloading
+ ? FUNC_NAME_TO_PTR(amagic_cmp_locale)
+ : FUNC_NAME_TO_PTR(sv_cmp_locale))
+ : ( overloading
+ ? FUNC_NAME_TO_PTR(amagic_cmp)
+ : FUNC_NAME_TO_PTR(sv_cmp) ));
}
}
LEAVE;
for (i = cxstack_ix; i >= 0; i--) {
cx = &cxstack[i];
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_SUBST:
- if (PL_dowarn)
- warn("Exiting substitution via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting substitution via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_SUB:
- if (PL_dowarn)
- warn("Exiting subroutine via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting subroutine via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_EVAL:
- if (PL_dowarn)
- warn("Exiting eval via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting eval via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_NULL:
- if (PL_dowarn)
- warn("Exiting pseudo-block via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting pseudo-block via %s",
+ PL_op_name[PL_op->op_type]);
return -1;
case CXt_LOOP:
if (!cx->blk_loop.label ||
register PERL_CONTEXT *cx;
for (i = startingblock; i >= 0; i--) {
cx = &cxstk[i];
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
default:
continue;
case CXt_EVAL:
register PERL_CONTEXT *cx;
for (i = startingblock; i >= 0; i--) {
cx = &cxstack[i];
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
default:
continue;
case CXt_EVAL:
register PERL_CONTEXT *cx;
for (i = startingblock; i >= 0; i--) {
cx = &cxstack[i];
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_SUBST:
- if (PL_dowarn)
- warn("Exiting substitution via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting substitution via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_SUB:
- if (PL_dowarn)
- warn("Exiting subroutine via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting subroutine via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_EVAL:
- if (PL_dowarn)
- warn("Exiting eval via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting eval via %s",
+ PL_op_name[PL_op->op_type]);
break;
case CXt_NULL:
- if (PL_dowarn)
- warn("Exiting pseudo-block via %s", op_name[PL_op->op_type]);
+ if (ckWARN(WARN_UNSAFE))
+ warner(WARN_UNSAFE, "Exiting pseudo-block via %s",
+ PL_op_name[PL_op->op_type]);
return -1;
case CXt_LOOP:
DEBUG_l( deb("(Found loop #%ld)\n", (long)i));
while (cxstack_ix > cxix) {
cx = &cxstack[cxstack_ix];
DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n",
- (long) cxstack_ix, block_type[cx->cx_type]));
+ (long) cxstack_ix, PL_block_type[CxTYPE(cx)]));
/* Note: we don't need to restore the base context info till the end. */
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_SUBST:
POPSUBST(cx);
continue; /* not break */
dounwind(cxix);
POPBLOCK(cx,PL_curpm);
- if (cx->cx_type != CXt_EVAL) {
+ if (CxTYPE(cx) != CXt_EVAL) {
PerlIO_printf(PerlIO_stderr(), "panic: die %s", message);
my_exit(1);
}
return pop_return();
}
}
+ if (!message)
+ message = SvPVx(ERRSV, PL_na);
PerlIO_printf(PerlIO_stderr(), "%s",message);
PerlIO_flush(PerlIO_stderr());
my_failure_exit();
}
cx = &ccstack[cxix];
- if (ccstack[cxix].cx_type == CXt_SUB) {
+ if (CxTYPE(cx) == CXt_SUB) {
dbcxix = dopoptosub_at(ccstack, cxix - 1);
/* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the
field below is defined for any cx. */
PUSHs(sv_2mortal(newSViv((I32)cx->blk_oldcop->cop_line)));
if (!MAXARG)
RETURN;
- if (cx->cx_type == CXt_SUB) { /* So is ccstack[dbcxix]. */
+ if (CxTYPE(cx) == CXt_SUB) { /* So is ccstack[dbcxix]. */
sv = NEWSV(49, 0);
gv_efullname3(sv, CvGV(ccstack[cxix].blk_sub.cv), Nullch);
PUSHs(sv_2mortal(sv));
PUSHs(&PL_sv_undef);
else
PUSHs(sv_2mortal(newSViv(gimme & G_ARRAY)));
- if (cx->cx_type == CXt_EVAL) {
+ if (CxTYPE(cx) == CXt_EVAL) {
if (cx->blk_eval.old_op_type == OP_ENTEREVAL) {
PUSHs(cx->blk_eval.cur_text);
PUSHs(&PL_sv_no);
PUSHs(&PL_sv_yes);
}
}
- else if (cx->cx_type == CXt_SUB &&
+ else if (CxTYPE(cx) == CXt_SUB &&
cx->blk_sub.hasargs &&
PL_curcop->cop_stash == PL_debstash)
{
dounwind(cxix);
POPBLOCK(cx,newpm);
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_SUB:
POPSUB1(cx); /* Delay POPSUB2 until stack values are safe */
popsub2 = TRUE;
dounwind(cxix);
POPBLOCK(cx,newpm);
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_LOOP:
POPLOOP1(cx); /* Delay POPLOOP2 until stack values are safe */
pop2 = CXt_LOOP;
SV** mark;
I32 items = 0;
I32 oldsave;
+ int arg_was_real = 0;
+ retry:
if (!CvROOT(cv) && !CvXSUB(cv)) {
- if (CvGV(cv)) {
- SV *tmpstr = sv_newmortal();
- gv_efullname3(tmpstr, CvGV(cv), Nullch);
+ GV *gv = CvGV(cv);
+ GV *autogv;
+ if (gv) {
+ SV *tmpstr;
+ /* autoloaded stub? */
+ if (cv != GvCV(gv) && (cv = GvCV(gv)))
+ goto retry;
+ autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv),
+ GvNAMELEN(gv), FALSE);
+ if (autogv && (cv = GvCV(autogv)))
+ goto retry;
+ tmpstr = sv_newmortal();
+ gv_efullname3(tmpstr, gv, Nullch);
DIE("Goto undefined subroutine &%s",SvPVX(tmpstr));
}
DIE("Goto undefined subroutine");
if (cxix < cxstack_ix)
dounwind(cxix);
TOPBLOCK(cx);
- if (cx->cx_type == CXt_EVAL && cx->blk_eval.old_op_type == OP_ENTEREVAL)
+ if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_op_type == OP_ENTEREVAL)
DIE("Can't goto subroutine from an eval-string");
mark = PL_stack_sp;
- if (cx->cx_type == CXt_SUB &&
+ if (CxTYPE(cx) == CXt_SUB &&
cx->blk_sub.hasargs) { /* put @_ back onto stack */
AV* av = cx->blk_sub.argarray;
SvREFCNT_dec(GvAV(PL_defgv));
GvAV(PL_defgv) = cx->blk_sub.savearray;
#endif /* USE_THREADS */
- AvREAL_off(av);
+ if (AvREAL(av)) {
+ arg_was_real = 1;
+ AvREAL_off(av); /* so av_clear() won't clobber elts */
+ }
av_clear(av);
}
else if (CvXSUB(cv)) { /* put GvAV(defgv) back onto stack */
Copy(AvARRAY(av), PL_stack_sp, items, SV*);
PL_stack_sp += items;
}
- if (cx->cx_type == CXt_SUB &&
+ if (CxTYPE(cx) == CXt_SUB &&
!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))
SvREFCNT_dec(cx->blk_sub.cv);
oldsave = PL_scopestack[PL_scopestack_ix - 1];
else {
AV* padlist = CvPADLIST(cv);
SV** svp = AvARRAY(padlist);
- if (cx->cx_type == CXt_EVAL) {
+ if (CxTYPE(cx) == CXt_EVAL) {
PL_in_eval = cx->blk_eval.old_in_eval;
PL_eval_root = cx->blk_eval.old_eval_root;
cx->cx_type = CXt_SUB;
if (CvDEPTH(cv) < 2)
(void)SvREFCNT_inc(cv);
else { /* save temporaries on recursion? */
- if (CvDEPTH(cv) == 100 && PL_dowarn)
+ if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
sub_crush_depth(cv);
if (CvDEPTH(cv) > AvFILLp(padlist)) {
AV *newpad = newAV();
}
Copy(mark,AvARRAY(av),items,SV*);
AvFILLp(av) = items - 1;
-
+ /* preserve @_ nature */
+ if (arg_was_real) {
+ AvREIFY_off(av);
+ AvREAL_on(av);
+ }
while (items--) {
if (*mark)
SvTEMP_off(*mark);
*enterops = 0;
for (ix = cxstack_ix; ix >= 0; ix--) {
cx = &cxstack[ix];
- switch (cx->cx_type) {
+ switch (CxTYPE(cx)) {
case CXt_EVAL:
gotoprobe = PL_eval_root; /* XXX not good for nested eval */
break;
PL_do_undump = FALSE;
}
- if (PL_top_env->je_prev) {
- PL_restartop = retop;
- JMPENV_JUMP(3);
- }
-
RETURNOP(retop);
}
JMPENV_PUSH(ret);
switch (ret) {
default: /* topmost level handles it */
+pass_the_buck:
JMPENV_POP;
PL_op = oldop;
JMPENV_JUMP(ret);
/* NOTREACHED */
case 3:
- if (!PL_restartop) {
- PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
- break;
- }
+ if (!PL_restartop)
+ goto pass_the_buck;
PL_op = PL_restartop;
PL_restartop = 0;
/* FALL THROUGH */
PL_hints = 0;
PL_op = &dummy;
- PL_op->op_type = 0; /* Avoid uninit warning. */
+ PL_op->op_type = OP_ENTEREVAL;
PL_op->op_flags = 0; /* Avoid uninit warning. */
PUSHBLOCK(cx, CXt_EVAL, SP);
PUSHEVAL(cx, 0, PL_compiling.cop_filegv);
POPEVAL(cx);
(*startop)->op_type = OP_NULL;
- (*startop)->op_ppaddr = ppaddr[OP_NULL];
+ (*startop)->op_ppaddr = PL_ppaddr[OP_NULL];
lex_end();
*avp = (AV*)SvREFCNT_inc(PL_comppad);
LEAVE;
+ if (PL_curcop == &PL_compiling)
+ PL_compiling.op_private = PL_hints;
#ifdef OP_IN_REGISTER
op = PL_opsave;
#endif
SAVEI32(PL_max_intro_pending);
caller = PL_compcv;
- for (i = cxstack_ix; i >= 0; i--) {
+ for (i = cxstack_ix - 1; i >= 0; i--) {
PERL_CONTEXT *cx = &cxstack[i];
- if (cx->cx_type == CXt_EVAL)
+ if (CxTYPE(cx) == CXt_EVAL)
break;
- else if (cx->cx_type == CXt_SUB) {
+ else if (CxTYPE(cx) == CXt_SUB) {
caller = cx->blk_sub.cv;
break;
}
#else
sv_setpvf(namesv, "%s/%s", dir, name);
#endif
+ TAINT_PROPER("require");
tryname = SvPVX(namesv);
tryrsfp = PerlIO_open(tryname, PERL_SCRIPT_MODE);
if (tryrsfp) {
RETPUSHUNDEF;
}
+ else
+ SETERRNO(0, SS$_NORMAL);
/* Assume success here to prevent recursive requirement. */
(void)hv_store(GvHVn(PL_incgv), name, strlen(name),
ENTER;
SAVETMPS;
lex_start(sv_2mortal(newSVpv("",0)));
- if (PL_rsfp_filters){
- save_aptr(&PL_rsfp_filters);
- PL_rsfp_filters = NULL;
- }
+ SAVEGENERICSV(PL_rsfp_filters);
+ PL_rsfp_filters = Nullav;
PL_rsfp = tryrsfp;
name = savepv(name);
SAVEFREEPV(name);
SAVEHINTS();
PL_hints = 0;
+ SAVEPPTR(PL_compiling.cop_warnings);
+ PL_compiling.cop_warnings = ((PL_dowarn & G_WARN_ALL_ON) ? WARN_ALL
+ : WARN_NONE);
/* switch to eval mode */
PUSHBLOCK(cx, CXt_EVAL, SP);
PUSHEVAL(cx, name, PL_compiling.cop_filegv);
+ SAVEI16(PL_compiling.cop_line);
PL_compiling.cop_line = 0;
PUTBACK;
SAVEDELETE(PL_defstash, safestr, strlen(safestr));
SAVEHINTS();
PL_hints = PL_op->op_targ;
+ SAVEPPTR(PL_compiling.cop_warnings);
+ if (PL_compiling.cop_warnings != WARN_ALL
+ && PL_compiling.cop_warnings != WARN_NONE){
+ PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
+ SAVEFREESV(PL_compiling.cop_warnings) ;
+ }
push_return(PL_op->op_next);
- PUSHBLOCK(cx, CXt_EVAL, SP);
+ PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
PUSHEVAL(cx, 0, PL_compiling.cop_filegv);
/* prepare to compile string */