if (op->op_private & OPpLVAL_INTRO)
sv = save_scalar((GV*)TOPs);
else if (op->op_private & OPpDEREF)
- provide_ref(op, sv);
+ vivify_ref(sv, op->op_private & OPpDEREF);
}
SETs(sv);
RETURN;
if (SvTYPE(sv) == SVt_PVLV && LvTYPE(sv) == 'y') {
if (LvTARGLEN(sv))
- vivify_itervar(sv);
- if (LvTARG(sv))
- sv = LvTARG(sv);
+ vivify_defelem(sv);
+ if (!(sv = LvTARG(sv)))
+ sv = &sv_undef;
}
else if (SvPADTMP(sv))
sv = newSVsv(sv);
PP(pp_predec)
{
dSP;
- if (SvREADONLY(TOPs))
+ if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
croak(no_modify);
if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
SvIVX(TOPs) != IV_MIN)
PP(pp_postinc)
{
dSP; dTARGET;
- if (SvREADONLY(TOPs))
+ if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
croak(no_modify);
sv_setsv(TARG, TOPs);
if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
PP(pp_postdec)
{
dSP; dTARGET;
- if(SvREADONLY(TOPs))
+ if(SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
croak(no_modify);
sv_setsv(TARG, TOPs);
if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
{
dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
{
- register UV right;
+ UV left;
+ UV right;
+ bool left_neg;
+ bool right_neg;
+ UV ans;
- right = POPu;
- if (!right)
- DIE("Illegal modulus zero");
+ if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+ IV i = SvIVX(POPs);
+ right = (right_neg = (i < 0)) ? -i : i;
+ }
+ else {
+ double n = POPn;
+ right = U_V((right_neg = (n < 0)) ? -n : n);
+ }
if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
- register IV left = SvIVX(TOPs);
- if (left < 0)
- SETu( (right - ((UV)(-left) - 1) % right) - 1 );
- else
- SETi( left % right );
+ IV i = SvIVX(POPs);
+ left = (left_neg = (i < 0)) ? -i : i;
}
else {
- register double left = TOPn;
- if (left < 0.0)
- SETu( (right - (U_V(-left) - 1) % right) - 1 );
+ double n = POPn;
+ left = U_V((left_neg = (n < 0)) ? -n : n);
+ }
+
+ if (!right)
+ DIE("Illegal modulus zero");
+
+ ans = left % right;
+ if ((left_neg != right_neg) && ans)
+ ans = right - ans;
+ if (right_neg) {
+ if (ans <= -(UV)IV_MAX)
+ sv_setiv(TARG, (IV) -ans);
else
- SETu( U_V(left) % right );
+ sv_setnv(TARG, -(double)ans);
}
+ else
+ sv_setuv(TARG, ans);
+ PUSHTARG;
RETURN;
}
}
static U32
seed()
{
+ /*
+ * This is really just a quick hack which grabs various garbage
+ * values. It really should be a real hash algorithm which
+ * spreads the effect of every input bit onto every output bit,
+ * if someone who knows about such tings would bother to write it.
+ * Might be a good idea to add that function to CORE as well.
+ * No numbers below come from careful analysis or anyting here,
+ * except they are primes and SEED_C1 > 1E6 to get a full-width
+ * value from (tv_sec * SEED_C1 + tv_usec). The multipliers should
+ * probably be bigger too.
+ */
+#if RANDBITS > 16
+# define SEED_C1 1000003
+#define SEED_C4 73819
+#else
+# define SEED_C1 25747
+#define SEED_C4 20639
+#endif
+#define SEED_C2 3
+#define SEED_C3 269
+#define SEED_C5 26107
+
U32 u;
#ifdef VMS
# include <starlet.h>
unsigned int when[2];
_ckvmssts(sys$gettim(when));
- u = when[0] ^ when[1];
+ /* Please tell us: Which value is seconds and what is the other here? */
+ u = (U32)SEED_C1 * when[0] + (U32)SEED_C2 * when[1];
#else
# ifdef HAS_GETTIMEOFDAY
struct timeval when;
gettimeofday(&when,(struct timezone *) 0);
- u = when.tv_sec ^ when.tv_usec;
+ u = (U32)SEED_C1 * when.tv_sec + (U32)SEED_C2 * when.tv_usec;
# else
Time_t when;
(void)time(&when);
- u = when;
+ u = (U32)SEED_C1 * when;
# endif
#endif
-#ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */
- /* What is a good hashing algorithm here? */
- u ^= ( ( 269 * (U32)getpid())
- ^ (26107 * (U32)&when)
- ^ (73819 * (U32)stack_sp));
+ u += SEED_C3 * (U32)getpid();
+ u += SEED_C4 * (U32)stack_sp;
+#ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */
+ u += SEED_C5 * (U32)&when;
#endif
return u;
}
tmps = SvPV(sv, curlen);
if (pos < 0) {
pos += curlen + arybase;
- if (pos < 0 && MAXARG < 3) pos = 0;
+ if (pos < 0 && MAXARG < 3)
+ pos = 0;
}
if (pos < 0 || pos > curlen) {
if (dowarn || lvalue)