X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp.c;h=8fbe61de71ca98f83d7708728531d91e75920d12;hb=0a5d5e8be390bda2f9b7684490082d428228d28f;hp=c288a01b30efcee15d67fc5567d6104e83e1419f;hpb=6d4ff0d2f86d3c242b3f29bee3c2734df9ab8a3a;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp.c b/pp.c index c288a01..8fbe61d 100644 --- a/pp.c +++ b/pp.c @@ -16,6 +16,17 @@ #include "perl.h" /* + * The compiler on Concurrent CX/UX systems has a subtle bug which only + * seems to show up when compiling pp.c - it generates the wrong double + * precision constant value for (double)UV_MAX when used inline in the body + * of the code below, so this makes a static variable up front (which the + * compiler seems to get correct) and uses it in place of UV_MAX below. + */ +#ifdef CXUX_BROKEN_CONSTANT_CONVERT +static double UV_MAX_cxux = ((double)UV_MAX); +#endif + +/* * Types used in bitwise operations. * * Normally we'd just use IV and UV. However, some hardware and @@ -89,17 +100,22 @@ typedef unsigned UBW; static void doencodes _((SV* sv, char* s, I32 len)); static SV* refto _((SV* sv)); static U32 seed _((void)); -#ifdef USE_THREADS -static void unlock_condpair _((void*)); -#endif /* USE_THREADS */ static bool srand_called = FALSE; /* variations on pp_null */ +#ifdef DONT_DECLARE_STD +#ifdef I_UNISTD +#include +#endif +#else +extern pid_t getpid (void); +#endif + PP(pp_stub) { - dSP; + djSP; if (GIMME_V == G_SCALAR) XPUSHs(&sv_undef); RETURN; @@ -114,7 +130,7 @@ PP(pp_scalar) PP(pp_padav) { - dSP; dTARGET; + djSP; dTARGET; if (op->op_private & OPpLVAL_INTRO) SAVECLEARSV(curpad[op->op_targ]); EXTEND(SP, 1); @@ -139,7 +155,7 @@ PP(pp_padav) PP(pp_padhv) { - dSP; dTARGET; + djSP; dTARGET; I32 gimme; XPUSHs(TARG); @@ -172,7 +188,7 @@ PP(pp_padany) PP(pp_rv2gv) { - dSP; dTOPss; + djSP; dTOPss; if (SvROK(sv)) { wasref: @@ -181,7 +197,7 @@ PP(pp_rv2gv) GV *gv = (GV*) sv_newmortal(); gv_init(gv, 0, "", 0, 0); GvIOp(gv) = (IO *)sv; - SvREFCNT_inc(sv); + (void)SvREFCNT_inc(sv); sv = (SV*) gv; } else if (SvTYPE(sv) != SVt_PVGV) DIE("Not a GLOB reference"); @@ -217,7 +233,7 @@ PP(pp_rv2gv) PP(pp_rv2sv) { - dSP; dTOPss; + djSP; dTOPss; if (SvROK(sv)) { wasref: @@ -266,7 +282,7 @@ PP(pp_rv2sv) PP(pp_av2arylen) { - dSP; + djSP; AV *av = (AV*)TOPs; SV *sv = AvARYLEN(av); if (!sv) { @@ -280,7 +296,7 @@ PP(pp_av2arylen) PP(pp_pos) { - dSP; dTARGET; dPOPss; + djSP; dTARGET; dPOPss; if (op->op_flags & OPf_MOD) { if (SvTYPE(TARG) < SVt_PVLV) { @@ -309,7 +325,7 @@ PP(pp_pos) PP(pp_rv2cv) { - dSP; + djSP; GV *gv; HV *stash; @@ -328,7 +344,7 @@ PP(pp_rv2cv) PP(pp_prototype) { - dSP; + djSP; CV *cv; HV *stash; GV *gv; @@ -344,7 +360,7 @@ PP(pp_prototype) PP(pp_anoncode) { - dSP; + djSP; CV* cv = (CV*)curpad[op->op_targ]; if (CvCLONE(cv)) cv = (CV*)sv_2mortal((SV*)cv_clone(cv)); @@ -355,14 +371,14 @@ PP(pp_anoncode) PP(pp_srefgen) { - dSP; + djSP; *SP = refto(*SP); RETURN; } PP(pp_refgen) { - dSP; dMARK; + djSP; dMARK; if (GIMME != G_ARRAY) { MARK[1] = *SP; SP = MARK + 1; @@ -374,8 +390,7 @@ PP(pp_refgen) } static SV* -refto(sv) -SV* sv; +refto(SV *sv) { SV* rv; @@ -388,7 +403,6 @@ SV* sv; else if (SvPADTMP(sv)) sv = newSVsv(sv); else { - dTHR; /* just for SvREFCNT_inc */ SvTEMP_off(sv); (void)SvREFCNT_inc(sv); } @@ -401,7 +415,7 @@ SV* sv; PP(pp_ref) { - dSP; dTARGET; + djSP; dTARGET; SV *sv; char *pv; @@ -421,7 +435,7 @@ PP(pp_ref) PP(pp_bless) { - dSP; + djSP; HV *stash; if (MAXARG == 1) @@ -433,11 +447,74 @@ PP(pp_bless) RETURN; } +PP(pp_gelem) +{ + GV *gv; + SV *sv; + SV *ref; + char *elem; + djSP; + + sv = POPs; + elem = SvPV(sv, na); + gv = (GV*)POPs; + ref = Nullsv; + sv = Nullsv; + switch (elem ? *elem : '\0') + { + case 'A': + if (strEQ(elem, "ARRAY")) + ref = (SV*)GvAV(gv); + break; + case 'C': + if (strEQ(elem, "CODE")) + ref = (SV*)GvCVu(gv); + break; + case 'F': + if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */ + ref = (SV*)GvIOp(gv); + break; + case 'G': + if (strEQ(elem, "GLOB")) + ref = (SV*)gv; + break; + case 'H': + if (strEQ(elem, "HASH")) + ref = (SV*)GvHV(gv); + break; + case 'I': + if (strEQ(elem, "IO")) + ref = (SV*)GvIOp(gv); + break; + case 'N': + if (strEQ(elem, "NAME")) + sv = newSVpv(GvNAME(gv), GvNAMELEN(gv)); + break; + case 'P': + if (strEQ(elem, "PACKAGE")) + sv = newSVpv(HvNAME(GvSTASH(gv)), 0); + break; + case 'S': + if (strEQ(elem, "SCALAR")) + ref = GvSV(gv); + break; + } + if (ref) + sv = newRV(ref); + if (sv) + sv_2mortal(sv); + else + sv = &sv_undef; + XPUSHs(sv); + RETURN; +} + /* Pattern matching */ PP(pp_study) { - dSP; dPOPss; + djSP; dPOPss; + register UNOP *unop = cUNOP; register unsigned char *s; register I32 pos; register I32 ch; @@ -445,6 +522,14 @@ PP(pp_study) register I32 *snext; STRLEN len; + if(unop->op_first && unop->op_first->op_type == OP_PUSHRE) { + PMOP *pm = (PMOP *)unop->op_first; + SV *rv = sv_newmortal(); + sv = newSVrv(rv, "Regexp"); + sv_magic(sv,(SV*)ReREFCNT_inc(pm->op_pmregexp),'r',0,0); + RETURNX(PUSHs(rv)); + } + if (sv == lastscream) { if (SvSCREAM(sv)) RETPUSHYES; @@ -499,13 +584,13 @@ PP(pp_study) PP(pp_trans) { - dSP; dTARG; + djSP; dTARG; SV *sv; if (op->op_flags & OPf_STACKED) sv = POPs; else { - sv = GvSV(defgv); + sv = DEFSV; EXTEND(SP,1); } TARG = sv_newmortal(); @@ -517,7 +602,7 @@ PP(pp_trans) PP(pp_schop) { - dSP; dTARGET; + djSP; dTARGET; do_chop(TARG, TOPs); SETTARG; RETURN; @@ -525,7 +610,7 @@ PP(pp_schop) PP(pp_chop) { - dSP; dMARK; dTARGET; + djSP; dMARK; dTARGET; while (SP > MARK) do_chop(TARG, POPs); PUSHTARG; @@ -534,14 +619,14 @@ PP(pp_chop) PP(pp_schomp) { - dSP; dTARGET; + djSP; dTARGET; SETi(do_chomp(TOPs)); RETURN; } PP(pp_chomp) { - dSP; dMARK; dTARGET; + djSP; dMARK; dTARGET; register I32 count = 0; while (SP > MARK) @@ -552,7 +637,7 @@ PP(pp_chomp) PP(pp_defined) { - dSP; + djSP; register SV* sv; sv = POPs; @@ -560,11 +645,11 @@ PP(pp_defined) RETPUSHNO; switch (SvTYPE(sv)) { case SVt_PVAV: - if (AvMAX(sv) >= 0 || SvRMAGICAL(sv)) + if (AvMAX(sv) >= 0 || SvGMAGICAL(sv)) RETPUSHYES; break; case SVt_PVHV: - if (HvARRAY(sv) || SvRMAGICAL(sv)) + if (HvARRAY(sv) || SvGMAGICAL(sv)) RETPUSHYES; break; case SVt_PVCV: @@ -582,7 +667,7 @@ PP(pp_defined) PP(pp_undef) { - dSP; + djSP; SV *sv; if (!op->op_private) { @@ -640,7 +725,7 @@ PP(pp_undef) PP(pp_predec) { - dSP; + djSP; if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) croak(no_modify); if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && @@ -657,7 +742,7 @@ PP(pp_predec) PP(pp_postinc) { - dSP; dTARGET; + djSP; dTARGET; if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) croak(no_modify); sv_setsv(TARG, TOPs); @@ -678,7 +763,7 @@ PP(pp_postinc) PP(pp_postdec) { - dSP; dTARGET; + djSP; dTARGET; if(SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV) croak(no_modify); sv_setsv(TARG, TOPs); @@ -699,7 +784,7 @@ PP(pp_postdec) PP(pp_pow) { - dSP; dATARGET; tryAMAGICbin(pow,opASSIGN); + djSP; dATARGET; tryAMAGICbin(pow,opASSIGN); { dPOPTOPnnrl; SETn( pow( left, right) ); @@ -709,7 +794,7 @@ PP(pp_pow) PP(pp_multiply) { - dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); + djSP; dATARGET; tryAMAGICbin(mult,opASSIGN); { dPOPTOPnnrl; SETn( left * right ); @@ -719,7 +804,7 @@ PP(pp_multiply) PP(pp_divide) { - dSP; dATARGET; tryAMAGICbin(div,opASSIGN); + djSP; dATARGET; tryAMAGICbin(div,opASSIGN); { dPOPPOPnnrl; double value; @@ -747,7 +832,7 @@ PP(pp_divide) PP(pp_modulo) { - dSP; dATARGET; tryAMAGICbin(mod,opASSIGN); + djSP; dATARGET; tryAMAGICbin(mod,opASSIGN); { UV left; UV right; @@ -780,8 +865,10 @@ PP(pp_modulo) if ((left_neg != right_neg) && ans) ans = right - ans; if (right_neg) { - if (ans <= -(UV)IV_MAX) - sv_setiv(TARG, (IV) -ans); + /* XXX may warn: unary minus operator applied to unsigned type */ + /* could change -foo to be (~foo)+1 instead */ + if (ans <= ~((UV)IV_MAX)+1) + sv_setiv(TARG, ~ans+1); else sv_setnv(TARG, -(double)ans); } @@ -794,7 +881,7 @@ PP(pp_modulo) PP(pp_repeat) { - dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN); + djSP; dATARGET; tryAMAGICbin(repeat,opASSIGN); { register I32 count = POPi; if (GIMME == G_ARRAY && op->op_private & OPpREPEAT_DOLIST) { @@ -850,7 +937,7 @@ PP(pp_repeat) PP(pp_subtract) { - dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); + djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); { dPOPTOPnnrl_ul; SETn( left - right ); @@ -860,7 +947,7 @@ PP(pp_subtract) PP(pp_left_shift) { - dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN); + djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN); { IBW shift = POPi; if (op->op_private & HINT_INTEGER) { @@ -879,7 +966,7 @@ PP(pp_left_shift) PP(pp_right_shift) { - dSP; dATARGET; tryAMAGICbin(rshift,opASSIGN); + djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN); { IBW shift = POPi; if (op->op_private & HINT_INTEGER) { @@ -898,7 +985,7 @@ PP(pp_right_shift) PP(pp_lt) { - dSP; tryAMAGICbinSET(lt,0); + djSP; tryAMAGICbinSET(lt,0); { dPOPnv; SETs(boolSV(TOPn < value)); @@ -908,7 +995,7 @@ PP(pp_lt) PP(pp_gt) { - dSP; tryAMAGICbinSET(gt,0); + djSP; tryAMAGICbinSET(gt,0); { dPOPnv; SETs(boolSV(TOPn > value)); @@ -918,7 +1005,7 @@ PP(pp_gt) PP(pp_le) { - dSP; tryAMAGICbinSET(le,0); + djSP; tryAMAGICbinSET(le,0); { dPOPnv; SETs(boolSV(TOPn <= value)); @@ -928,7 +1015,7 @@ PP(pp_le) PP(pp_ge) { - dSP; tryAMAGICbinSET(ge,0); + djSP; tryAMAGICbinSET(ge,0); { dPOPnv; SETs(boolSV(TOPn >= value)); @@ -938,7 +1025,7 @@ PP(pp_ge) PP(pp_ne) { - dSP; tryAMAGICbinSET(ne,0); + djSP; tryAMAGICbinSET(ne,0); { dPOPnv; SETs(boolSV(TOPn != value)); @@ -948,7 +1035,7 @@ PP(pp_ne) PP(pp_ncmp) { - dSP; dTARGET; tryAMAGICbin(ncmp,0); + djSP; dTARGET; tryAMAGICbin(ncmp,0); { dPOPTOPnnrl; I32 value; @@ -970,7 +1057,7 @@ PP(pp_ncmp) PP(pp_slt) { - dSP; tryAMAGICbinSET(slt,0); + djSP; tryAMAGICbinSET(slt,0); { dPOPTOPssrl; int cmp = ((op->op_private & OPpLOCALE) @@ -983,7 +1070,7 @@ PP(pp_slt) PP(pp_sgt) { - dSP; tryAMAGICbinSET(sgt,0); + djSP; tryAMAGICbinSET(sgt,0); { dPOPTOPssrl; int cmp = ((op->op_private & OPpLOCALE) @@ -996,7 +1083,7 @@ PP(pp_sgt) PP(pp_sle) { - dSP; tryAMAGICbinSET(sle,0); + djSP; tryAMAGICbinSET(sle,0); { dPOPTOPssrl; int cmp = ((op->op_private & OPpLOCALE) @@ -1009,7 +1096,7 @@ PP(pp_sle) PP(pp_sge) { - dSP; tryAMAGICbinSET(sge,0); + djSP; tryAMAGICbinSET(sge,0); { dPOPTOPssrl; int cmp = ((op->op_private & OPpLOCALE) @@ -1022,7 +1109,7 @@ PP(pp_sge) PP(pp_seq) { - dSP; tryAMAGICbinSET(seq,0); + djSP; tryAMAGICbinSET(seq,0); { dPOPTOPssrl; SETs(boolSV(sv_eq(left, right))); @@ -1032,7 +1119,7 @@ PP(pp_seq) PP(pp_sne) { - dSP; tryAMAGICbinSET(sne,0); + djSP; tryAMAGICbinSET(sne,0); { dPOPTOPssrl; SETs(boolSV(!sv_eq(left, right))); @@ -1042,7 +1129,7 @@ PP(pp_sne) PP(pp_scmp) { - dSP; dTARGET; tryAMAGICbin(scmp,0); + djSP; dTARGET; tryAMAGICbin(scmp,0); { dPOPTOPssrl; int cmp = ((op->op_private & OPpLOCALE) @@ -1055,7 +1142,7 @@ PP(pp_scmp) PP(pp_bit_and) { - dSP; dATARGET; tryAMAGICbin(band,opASSIGN); + djSP; dATARGET; tryAMAGICbin(band,opASSIGN); { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { @@ -1078,7 +1165,7 @@ PP(pp_bit_and) PP(pp_bit_xor) { - dSP; dATARGET; tryAMAGICbin(bxor,opASSIGN); + djSP; dATARGET; tryAMAGICbin(bxor,opASSIGN); { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { @@ -1101,7 +1188,7 @@ PP(pp_bit_xor) PP(pp_bit_or) { - dSP; dATARGET; tryAMAGICbin(bor,opASSIGN); + djSP; dATARGET; tryAMAGICbin(bor,opASSIGN); { dPOPTOPssrl; if (SvNIOKp(left) || SvNIOKp(right)) { @@ -1124,7 +1211,7 @@ PP(pp_bit_or) PP(pp_negate) { - dSP; dTARGET; tryAMAGICun(neg); + djSP; dTARGET; tryAMAGICun(neg); { dTOPss; if (SvGMAGICAL(sv)) @@ -1157,7 +1244,7 @@ PP(pp_negate) PP(pp_not) { #ifdef OVERLOAD - dSP; tryAMAGICunSET(not); + djSP; tryAMAGICunSET(not); #endif /* OVERLOAD */ *stack_sp = boolSV(!SvTRUE(*stack_sp)); return NORMAL; @@ -1165,7 +1252,7 @@ PP(pp_not) PP(pp_complement) { - dSP; dTARGET; tryAMAGICun(compl); + djSP; dTARGET; tryAMAGICun(compl); { dTOPss; if (SvNIOKp(sv)) { @@ -1208,7 +1295,7 @@ PP(pp_complement) PP(pp_i_multiply) { - dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); + djSP; dATARGET; tryAMAGICbin(mult,opASSIGN); { dPOPTOPiirl; SETi( left * right ); @@ -1218,7 +1305,7 @@ PP(pp_i_multiply) PP(pp_i_divide) { - dSP; dATARGET; tryAMAGICbin(div,opASSIGN); + djSP; dATARGET; tryAMAGICbin(div,opASSIGN); { dPOPiv; if (value == 0) @@ -1231,7 +1318,7 @@ PP(pp_i_divide) PP(pp_i_modulo) { - dSP; dATARGET; tryAMAGICbin(mod,opASSIGN); + djSP; dATARGET; tryAMAGICbin(mod,opASSIGN); { dPOPTOPiirl; if (!right) @@ -1243,7 +1330,7 @@ PP(pp_i_modulo) PP(pp_i_add) { - dSP; dATARGET; tryAMAGICbin(add,opASSIGN); + djSP; dATARGET; tryAMAGICbin(add,opASSIGN); { dPOPTOPiirl; SETi( left + right ); @@ -1253,7 +1340,7 @@ PP(pp_i_add) PP(pp_i_subtract) { - dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); + djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); { dPOPTOPiirl; SETi( left - right ); @@ -1263,7 +1350,7 @@ PP(pp_i_subtract) PP(pp_i_lt) { - dSP; tryAMAGICbinSET(lt,0); + djSP; tryAMAGICbinSET(lt,0); { dPOPTOPiirl; SETs(boolSV(left < right)); @@ -1273,7 +1360,7 @@ PP(pp_i_lt) PP(pp_i_gt) { - dSP; tryAMAGICbinSET(gt,0); + djSP; tryAMAGICbinSET(gt,0); { dPOPTOPiirl; SETs(boolSV(left > right)); @@ -1283,7 +1370,7 @@ PP(pp_i_gt) PP(pp_i_le) { - dSP; tryAMAGICbinSET(le,0); + djSP; tryAMAGICbinSET(le,0); { dPOPTOPiirl; SETs(boolSV(left <= right)); @@ -1293,7 +1380,7 @@ PP(pp_i_le) PP(pp_i_ge) { - dSP; tryAMAGICbinSET(ge,0); + djSP; tryAMAGICbinSET(ge,0); { dPOPTOPiirl; SETs(boolSV(left >= right)); @@ -1303,7 +1390,7 @@ PP(pp_i_ge) PP(pp_i_eq) { - dSP; tryAMAGICbinSET(eq,0); + djSP; tryAMAGICbinSET(eq,0); { dPOPTOPiirl; SETs(boolSV(left == right)); @@ -1313,7 +1400,7 @@ PP(pp_i_eq) PP(pp_i_ne) { - dSP; tryAMAGICbinSET(ne,0); + djSP; tryAMAGICbinSET(ne,0); { dPOPTOPiirl; SETs(boolSV(left != right)); @@ -1323,7 +1410,7 @@ PP(pp_i_ne) PP(pp_i_ncmp) { - dSP; dTARGET; tryAMAGICbin(ncmp,0); + djSP; dTARGET; tryAMAGICbin(ncmp,0); { dPOPTOPiirl; I32 value; @@ -1341,7 +1428,7 @@ PP(pp_i_ncmp) PP(pp_i_negate) { - dSP; dTARGET; tryAMAGICun(neg); + djSP; dTARGET; tryAMAGICun(neg); SETi(-TOPi); RETURN; } @@ -1350,7 +1437,7 @@ PP(pp_i_negate) PP(pp_atan2) { - dSP; dTARGET; tryAMAGICbin(atan2,0); + djSP; dTARGET; tryAMAGICbin(atan2,0); { dPOPTOPnnrl; SETn(atan2(left, right)); @@ -1360,7 +1447,7 @@ PP(pp_atan2) PP(pp_sin) { - dSP; dTARGET; tryAMAGICun(sin); + djSP; dTARGET; tryAMAGICun(sin); { double value; value = POPn; @@ -1372,7 +1459,7 @@ PP(pp_sin) PP(pp_cos) { - dSP; dTARGET; tryAMAGICun(cos); + djSP; dTARGET; tryAMAGICun(cos); { double value; value = POPn; @@ -1384,7 +1471,7 @@ PP(pp_cos) PP(pp_rand) { - dSP; dTARGET; + djSP; dTARGET; double value; if (MAXARG < 1) value = 1.0; @@ -1415,7 +1502,7 @@ PP(pp_rand) PP(pp_srand) { - dSP; + djSP; UV anum; if (MAXARG < 1) anum = seed(); @@ -1428,7 +1515,7 @@ PP(pp_srand) } static U32 -seed() +seed(void) { /* * This is really just a quick hack which grabs various garbage @@ -1482,7 +1569,7 @@ seed() PP(pp_exp) { - dSP; dTARGET; tryAMAGICun(exp); + djSP; dTARGET; tryAMAGICun(exp); { double value; value = POPn; @@ -1494,7 +1581,7 @@ PP(pp_exp) PP(pp_log) { - dSP; dTARGET; tryAMAGICun(log); + djSP; dTARGET; tryAMAGICun(log); { double value; value = POPn; @@ -1510,7 +1597,7 @@ PP(pp_log) PP(pp_sqrt) { - dSP; dTARGET; tryAMAGICun(sqrt); + djSP; dTARGET; tryAMAGICun(sqrt); { double value; value = POPn; @@ -1526,7 +1613,7 @@ PP(pp_sqrt) PP(pp_int) { - dSP; dTARGET; + djSP; dTARGET; { double value = TOPn; IV iv; @@ -1554,7 +1641,7 @@ PP(pp_int) PP(pp_abs) { - dSP; dTARGET; tryAMAGICun(abs); + djSP; dTARGET; tryAMAGICun(abs); { double value = TOPn; IV iv; @@ -1576,7 +1663,7 @@ PP(pp_abs) PP(pp_hex) { - dSP; dTARGET; + djSP; dTARGET; char *tmps; I32 argtype; @@ -1587,7 +1674,7 @@ PP(pp_hex) PP(pp_oct) { - dSP; dTARGET; + djSP; dTARGET; UV value; I32 argtype; char *tmps; @@ -1609,50 +1696,69 @@ PP(pp_oct) PP(pp_length) { - dSP; dTARGET; + djSP; dTARGET; SETi( sv_len(TOPs) ); RETURN; } PP(pp_substr) { - dSP; dTARGET; + djSP; dTARGET; SV *sv; I32 len; STRLEN curlen; I32 pos; I32 rem; + I32 fail; I32 lvalue = op->op_flags & OPf_MOD; char *tmps; I32 arybase = curcop->cop_arybase; if (MAXARG > 2) len = POPi; - pos = POPi - arybase; + pos = POPi; sv = POPs; tmps = SvPV(sv, curlen); - if (pos < 0) { - pos += curlen + arybase; - if (pos < 0 && MAXARG < 3) - pos = 0; + if (pos >= arybase) { + pos -= arybase; + rem = curlen-pos; + fail = rem; + if (MAXARG > 2) { + if (len < 0) { + rem += len; + if (rem < 0) + rem = 0; + } + else if (rem > len) + rem = len; + } } - if (pos < 0 || pos > curlen) { - if (dowarn || lvalue) + else { + pos += curlen; + if (MAXARG < 3) + rem = curlen; + else if (len >= 0) { + rem = pos+len; + if (rem > (I32)curlen) + rem = curlen; + } + else { + rem = curlen+len; + if (rem < pos) + rem = pos; + } + if (pos < 0) + pos = 0; + fail = rem; + rem -= pos; + } + if (fail < 0) { + if (dowarn || lvalue) warn("substr outside of string"); RETPUSHUNDEF; } else { - if (MAXARG < 3) - len = curlen; - else if (len < 0) { - len += curlen - pos; - if (len < 0) - len = 0; - } tmps += pos; - rem = curlen - pos; /* rem=how many bytes left*/ - if (rem > len) - rem = len; sv_setpvn(TARG, tmps, rem); if (lvalue) { /* it's an lvalue! */ if (!SvGMAGICAL(sv)) { @@ -1684,7 +1790,7 @@ PP(pp_substr) PP(pp_vec) { - dSP; dTARGET; + djSP; dTARGET; register I32 size = POPi; register I32 offset = POPi; register SV *src = POPs; @@ -1758,7 +1864,7 @@ PP(pp_vec) PP(pp_index) { - dSP; dTARGET; + djSP; dTARGET; SV *big; SV *little; I32 offset; @@ -1790,7 +1896,7 @@ PP(pp_index) PP(pp_rindex) { - dSP; dTARGET; + djSP; dTARGET; SV *big; SV *little; STRLEN blen; @@ -1827,7 +1933,7 @@ PP(pp_rindex) PP(pp_sprintf) { - dSP; dMARK; dORIGMARK; dTARGET; + djSP; dMARK; dORIGMARK; dTARGET; #ifdef USE_LOCALE_NUMERIC if (op->op_private & OPpLOCALE) SET_NUMERIC_LOCAL(); @@ -1843,7 +1949,7 @@ PP(pp_sprintf) PP(pp_ord) { - dSP; dTARGET; + djSP; dTARGET; I32 value; char *tmps; @@ -1862,7 +1968,7 @@ PP(pp_ord) PP(pp_chr) { - dSP; dTARGET; + djSP; dTARGET; char *tmps; (void)SvUPGRADE(TARG,SVt_PV); @@ -1878,7 +1984,7 @@ PP(pp_chr) PP(pp_crypt) { - dSP; dTARGET; dPOPTOPssrl; + djSP; dTARGET; dPOPTOPssrl; #ifdef HAS_CRYPT char *tmps = SvPV(left, na); #ifdef FCRYPT @@ -1896,7 +2002,7 @@ PP(pp_crypt) PP(pp_ucfirst) { - dSP; + djSP; SV *sv = TOPs; register char *s; @@ -1922,7 +2028,7 @@ PP(pp_ucfirst) PP(pp_lcfirst) { - dSP; + djSP; SV *sv = TOPs; register char *s; @@ -1949,7 +2055,7 @@ PP(pp_lcfirst) PP(pp_uc) { - dSP; + djSP; SV *sv = TOPs; register char *s; STRLEN len; @@ -1981,7 +2087,7 @@ PP(pp_uc) PP(pp_lc) { - dSP; + djSP; SV *sv = TOPs; register char *s; STRLEN len; @@ -2013,7 +2119,7 @@ PP(pp_lc) PP(pp_quotemeta) { - dSP; dTARGET; + djSP; dTARGET; SV *sv = TOPs; STRLEN len; register char *s = SvPV(sv,len); @@ -2042,7 +2148,7 @@ PP(pp_quotemeta) PP(pp_aslice) { - dSP; dMARK; dORIGMARK; + djSP; dMARK; dORIGMARK; register SV** svp; register AV* av = (AV*)POPs; register I32 lval = op->op_flags & OPf_MOD; @@ -2087,7 +2193,7 @@ PP(pp_aslice) PP(pp_each) { - dSP; dTARGET; + djSP; dTARGET; HV *hash = (HV*)POPs; HE *entry; I32 gimme = GIMME_V; @@ -2128,7 +2234,7 @@ PP(pp_keys) PP(pp_delete) { - dSP; + djSP; I32 gimme = GIMME_V; I32 discard = (gimme == G_VOID) ? G_DISCARD : 0; SV *sv; @@ -2175,7 +2281,7 @@ PP(pp_delete) PP(pp_exists) { - dSP; + djSP; SV *tmpsv = POPs; HV *hv = (HV*)POPs; if (SvTYPE(hv) == SVt_PVHV) { @@ -2192,7 +2298,7 @@ PP(pp_exists) PP(pp_hslice) { - dSP; dMARK; dORIGMARK; + djSP; dMARK; dORIGMARK; register HE *he; register HV *hv = (HV*)POPs; register I32 lval = op->op_flags & OPf_MOD; @@ -2229,7 +2335,7 @@ PP(pp_hslice) PP(pp_list) { - dSP; dMARK; + djSP; dMARK; if (GIMME != G_ARRAY) { if (++MARK <= SP) *MARK = *SP; /* unwanted list, return last item */ @@ -2242,7 +2348,7 @@ PP(pp_list) PP(pp_lslice) { - dSP; + djSP; SV **lastrelem = stack_sp; SV **lastlelem = stack_base + POPMARK; SV **firstlelem = stack_base + POPMARK + 1; @@ -2300,7 +2406,7 @@ PP(pp_lslice) PP(pp_anonlist) { - dSP; dMARK; dORIGMARK; + djSP; dMARK; dORIGMARK; I32 items = SP - MARK; SV *av = sv_2mortal((SV*)av_make(items, MARK+1)); SP = ORIGMARK; /* av_make() might realloc stack_sp */ @@ -2310,7 +2416,7 @@ PP(pp_anonlist) PP(pp_anonhash) { - dSP; dMARK; dORIGMARK; + djSP; dMARK; dORIGMARK; HV* hv = (HV*)sv_2mortal((SV*)newHV()); while (MARK < SP) { @@ -2318,7 +2424,7 @@ PP(pp_anonhash) SV *val = NEWSV(46, 0); if (MARK < SP) sv_setsv(val, *++MARK); - else + else if (dowarn) warn("Odd number of elements in hash list"); (void)hv_store_ent(hv,key,val,0); } @@ -2329,7 +2435,7 @@ PP(pp_anonhash) PP(pp_splice) { - dSP; dMARK; dORIGMARK; + djSP; dMARK; dORIGMARK; register AV *ary = (AV*)*++MARK; register SV **src; register SV **dst; @@ -2344,11 +2450,13 @@ PP(pp_splice) SP++; if (++MARK < SP) { - offset = SvIVx(*MARK); + offset = i = SvIVx(*MARK); if (offset < 0) offset += AvFILL(ary) + 1; else offset -= curcop->cop_arybase; + if (offset < 0) + DIE(no_aelem, i); if (++MARK < SP) { length = SvIVx(*MARK++); if (length < 0) @@ -2361,12 +2469,6 @@ PP(pp_splice) offset = 0; length = AvMAX(ary) + 1; } - if (offset < 0) { - length += offset; - offset = 0; - if (length < 0) - length = 0; - } if (offset > AvFILL(ary) + 1) offset = AvFILL(ary) + 1; after = AvFILL(ary) + 1 - (offset + length); @@ -2381,6 +2483,12 @@ PP(pp_splice) newlen = SP - MARK; diff = newlen - length; + if (newlen && !AvREAL(ary)) { + if (AvREIFY(ary)) + av_reify(ary); + else + assert(AvREAL(ary)); /* would leak, so croak */ + } if (diff < 0) { /* shrinking the area */ if (newlen) { @@ -2522,7 +2630,7 @@ PP(pp_splice) PP(pp_push) { - dSP; dMARK; dORIGMARK; dTARGET; + djSP; dMARK; dORIGMARK; dTARGET; register AV *ary = (AV*)*++MARK; register SV *sv = &sv_undef; @@ -2539,7 +2647,7 @@ PP(pp_push) PP(pp_pop) { - dSP; + djSP; AV *av = (AV*)POPs; SV *sv = av_pop(av); if (!SvIMMORTAL(sv) && AvREAL(av)) @@ -2550,7 +2658,7 @@ PP(pp_pop) PP(pp_shift) { - dSP; + djSP; AV *av = (AV*)POPs; SV *sv = av_shift(av); EXTEND(SP, 1); @@ -2564,7 +2672,7 @@ PP(pp_shift) PP(pp_unshift) { - dSP; dMARK; dORIGMARK; dTARGET; + djSP; dMARK; dORIGMARK; dTARGET; register AV *ary = (AV*)*++MARK; register SV *sv; register I32 i = 0; @@ -2583,7 +2691,7 @@ PP(pp_unshift) PP(pp_reverse) { - dSP; dMARK; + djSP; dMARK; register SV *tmp; SV **oldsp = SP; @@ -2606,7 +2714,7 @@ PP(pp_reverse) if (SP - MARK > 1) do_join(TARG, &sv_no, MARK, SP); else - sv_setsv(TARG, (SP > MARK) ? *SP : GvSV(defgv)); + sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV); up = SvPV_force(TARG, len); if (len > 1) { down = SvPVX(TARG) + len - 1; @@ -2624,9 +2732,7 @@ PP(pp_reverse) } static SV * -mul128(sv, m) - SV *sv; - U8 m; +mul128(SV *sv, U8 m) { STRLEN len; char *s = SvPV(sv, len); @@ -2634,11 +2740,11 @@ mul128(sv, m) U32 i = 0; if (!strnEQ(s, "0000", 4)) { /* need to grow sv */ - SV *new = newSVpv("0000000000", 10); + SV *New = newSVpv("0000000000", 10); - sv_catsv(new, sv); + sv_catsv(New, sv); SvREFCNT_dec(sv); /* free old sv */ - sv = new; + sv = New; s = SvPV(sv, len); } t = s + len - 1; @@ -2656,7 +2762,7 @@ mul128(sv, m) PP(pp_unpack) { - dSP; + djSP; dPOPPOPssrl; SV **oldsp = sp; I32 gimme = GIMME_V; @@ -2692,6 +2798,7 @@ PP(pp_unpack) register U32 culong; double cdouble; static char* bitcount = 0; + int commas = 0; if (gimme != G_ARRAY) { /* arrange to do first one only */ /*SUPPRESS 530*/ @@ -2725,6 +2832,10 @@ PP(pp_unpack) switch(datumtype) { default: croak("Invalid type in unpack: '%c'", (int)datumtype); + case ',': /* grandfather in commas but with a warning */ + if (commas++ == 0 && dowarn) + warn("Invalid type in unpack: '%c'", (int)datumtype); + break; case '%': if (len == 1 && pat[-1] != '1') len = 16; @@ -3289,10 +3400,10 @@ PP(pp_unpack) d = (*s++ - ' ') & 077; else d = 0; - hunk[0] = a << 2 | b >> 4; - hunk[1] = b << 4 | c >> 2; - hunk[2] = c << 6 | d; - sv_catpvn(sv, hunk, len > 3 ? 3 : len); + hunk[0] = (a << 2) | (b >> 4); + hunk[1] = (b << 4) | (c >> 2); + hunk[2] = (c << 6) | d; + sv_catpvn(sv, hunk, (len > 3) ? 3 : len); len -= 3; } if (*s == '\n') @@ -3343,10 +3454,7 @@ PP(pp_unpack) } static void -doencodes(sv, s, len) -register SV *sv; -register char *s; -register I32 len; +doencodes(register SV *sv, register char *s, register I32 len) { char hunk[5]; @@ -3355,8 +3463,8 @@ register I32 len; hunk[4] = '\0'; while (len > 0) { hunk[0] = ' ' + (077 & (*s >> 2)); - hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017)); - hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03)); + hunk[1] = ' ' + (077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))); + hunk[2] = ' ' + (077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))); hunk[3] = ' ' + (077 & (s[2] & 077)); sv_catpvn(sv, hunk, 4); s += 3; @@ -3370,9 +3478,7 @@ register I32 len; } static SV * -is_an_int(s, l) - char *s; - STRLEN l; +is_an_int(char *s, STRLEN l) { SV *result = newSVpv("", l); char *result_c = SvPV(result, na); /* convenience */ @@ -3420,9 +3526,9 @@ is_an_int(s, l) } static int -div128(pnum, done) - SV *pnum; /* must be '\0' terminated */ - bool *done; +div128(SV *pnum, char *done) + /* must be '\0' terminated */ + { STRLEN len; char *s = SvPV(pnum, len); @@ -3450,7 +3556,7 @@ div128(pnum, done) PP(pp_pack) { - dSP; dMARK; dORIGMARK; dTARGET; + djSP; dMARK; dORIGMARK; dTARGET; register SV *cat = TARG; register I32 items; STRLEN fromlen; @@ -3477,6 +3583,7 @@ PP(pp_pack) char *aptr; float afloat; double adouble; + int commas = 0; items = SP - MARK; MARK++; @@ -3500,6 +3607,10 @@ PP(pp_pack) switch(datumtype) { default: croak("Invalid type in pack: '%c'", (int)datumtype); + case ',': /* grandfather in commas but with a warning */ + if (commas++ == 0 && dowarn) + warn("Invalid type in pack: '%c'", (int)datumtype); + break; case '%': DIE("%% may only be used in unpack"); case '@': @@ -3741,8 +3852,12 @@ PP(pp_pack) #ifdef BW_BITS adouble <= BW_MASK #else +#ifdef CXUX_BROKEN_CONSTANT_CONVERT + adouble <= UV_MAX_cxux +#else adouble <= UV_MAX #endif +#endif ) { char buf[1 + sizeof(UV)]; @@ -3858,7 +3973,21 @@ PP(pp_pack) case 'p': while (len-- > 0) { fromstr = NEXTFROM; - aptr = SvPV_force(fromstr, na); /* XXX Error if TEMP? */ + if (fromstr == &sv_undef) + aptr = NULL; + else { + /* XXX better yet, could spirit away the string to + * a safe spot and hang on to it until the result + * of pack() (and all copies of the result) are + * gone. + */ + if (dowarn && (SvTEMP(fromstr) || SvPADTMP(fromstr))) + warn("Attempt to pack pointer to temporary value"); + if (SvPOK(fromstr) || SvNIOK(fromstr)) + aptr = SvPV(fromstr,na); + else + aptr = SvPV_force(fromstr,na); + } sv_catpvn(cat, (char*)&aptr, sizeof(char*)); } break; @@ -3893,7 +4022,7 @@ PP(pp_pack) PP(pp_split) { - dSP; dTARG; + djSP; dTARG; AV *ary; register I32 limit = POPi; /* note, negative is forever */ SV *sv = POPs; @@ -4006,10 +4135,12 @@ PP(pp_split) s = m; } } - else if (pm->op_pmshort && !rx->nparens) { - i = SvCUR(pm->op_pmshort); - if (i == 1) { - i = *SvPVX(pm->op_pmshort); + else if (rx->check_substr && !rx->nparens + && (rx->reganch & ROPT_CHECK_ALL) + && !(rx->reganch & ROPT_ANCH)) { + i = SvCUR(rx->check_substr); + if (i == 1 && !SvTAIL(rx->check_substr)) { + i = *SvPVX(rx->check_substr); while (--limit) { /*SUPPRESS 530*/ for (m = s; m < strend && *m != i; m++) ; @@ -4027,7 +4158,7 @@ PP(pp_split) #ifndef lint while (s < strend && --limit && (m=fbm_instr((unsigned char*)s, (unsigned char*)strend, - pm->op_pmshort)) ) + rx->check_substr)) ) #endif { dstr = NEWSV(31, m-s); @@ -4042,9 +4173,9 @@ PP(pp_split) else { maxiters += (strend - s) * rx->nparens; while (s < strend && --limit && - pregexec(rx, s, strend, orig, 1, Nullsv, TRUE)) + regexec_flags(rx, s, strend, orig, 1, Nullsv, NULL, 0)) { - TAINT_IF(rx->exec_tainted); + TAINT_IF(RX_MATCH_TAINTED(rx)); if (rx->subbase && rx->subbase != orig) { m = s; @@ -4097,6 +4228,11 @@ PP(pp_split) } if (realarray) { SWITCHSTACK(ary, oldstack); + if (SvSMAGICAL(ary)) { + PUTBACK; + mg_set((SV*)ary); + SPAGAIN; + } if (gimme == G_ARRAY) { EXTEND(SP, iters); Copy(AvARRAY(ary), SP + 1, iters, SV*); @@ -4117,9 +4253,8 @@ PP(pp_split) } #ifdef USE_THREADS -static void -unlock_condpair(svv) -void *svv; +void +unlock_condpair(void *svv) { dTHR; MAGIC *mg = mg_find((SV*)svv, 'm'); @@ -4131,15 +4266,18 @@ void *svv; croak("panic: unlock_condpair unlocking mutex that we don't own"); MgOWNER(mg) = 0; COND_SIGNAL(MgOWNERCONDP(mg)); + DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: unlock 0x%lx\n", + (unsigned long)thr, (unsigned long)svv);) MUTEX_UNLOCK(MgMUTEXP(mg)); } #endif /* USE_THREADS */ PP(pp_lock) { - dSP; -#ifdef USE_THREADS + djSP; dTOPss; + SV *retsv = sv; +#ifdef USE_THREADS MAGIC *mg; if (SvROK(sv)) @@ -4153,10 +4291,32 @@ PP(pp_lock) while (MgOWNER(mg)) COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg)); MgOWNER(mg) = thr; + DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n", + (unsigned long)thr, (unsigned long)sv);) MUTEX_UNLOCK(MgMUTEXP(mg)); + SvREFCNT_inc(sv); /* keep alive until magic_mutexfree */ save_destructor(unlock_condpair, sv); } #endif /* USE_THREADS */ - PUSHs(&sv_yes); + if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV + || SvTYPE(retsv) == SVt_PVCV) { + retsv = refto(retsv); + } + SETs(retsv); + RETURN; +} + +PP(pp_threadsv) +{ + djSP; +#ifdef USE_THREADS + EXTEND(sp, 1); + if (op->op_private & OPpLVAL_INTRO) + PUSHs(*save_threadsv(op->op_targ)); + else + PUSHs(*av_fetch(thr->threadsv, op->op_targ, FALSE)); +#else + DIE("tried to access per-thread data in non-threaded perl"); +#endif /* USE_THREADS */ RETURN; }