This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
More descriptive names for operators.
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 4d96370..07bb33d 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -28,6 +28,37 @@ 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
+ * software combinations (e.g. Alpha and current OSF/1) don't have a
+ * floating-point type to use for NV that has adequate bits to fully
+ * hold an IV/UV.  (In other words, sizeof(long) == sizeof(double).)
+ *
+ * It just so happens that "int" is the right size almost everywhere.
+ */
+typedef int IBW;
+typedef unsigned UBW;
+
+/*
+ * Mask used after bitwise operations.
+ *
+ * There is at least one realm (Cray word machines) that doesn't
+ * have an integral type (except char) small enough to be represented
+ * in a double without loss; that is, it has no 32-bit type.
+ */
+#if LONGSIZE > 4  && defined(_CRAY) && !defined(_CRAYMPP)
+#  define BW_BITS  32
+#  define BW_MASK  ((1 << BW_BITS) - 1)
+#  define BW_SIGN  (1 << (BW_BITS - 1))
+#  define BWi(i)  (((i) & BW_SIGN) ? ((i) | ~BW_MASK) : ((i) & BW_MASK))
+#  define BWu(u)  ((u) & BW_MASK)
+#else
+#  define BWi(i)  (i)
+#  define BWu(u)  (u)
+#endif
+
+/*
  * Offset for integer pack/unpack.
  *
  * On architectures where I16 and I32 aren't really 16 and 32 bits,
@@ -1102,11 +1133,17 @@ PP(pp_left_shift)
 {
     djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
     {
-      IV shift = POPi;
-      if (PL_op->op_private & HINT_INTEGER)
-       SETi(TOPi << shift);
-      else
-       SETu(TOPu << shift);
+      IBW shift = POPi;
+      if (PL_op->op_private & HINT_INTEGER) {
+       IBW i = TOPi;
+       i = BWi(i) << shift;
+       SETi(BWi(i));
+      }
+      else {
+       UBW u = TOPu;
+       u <<= shift;
+       SETu(BWu(u));
+      }
       RETURN;
     }
 }
@@ -1115,11 +1152,17 @@ PP(pp_right_shift)
 {
     djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
     {
-      IV shift = POPi;
-      if (PL_op->op_private & HINT_INTEGER)
-       SETi(TOPi >> shift);
-      else
-       SETu(TOPu >> shift);
+      IBW shift = POPi;
+      if (PL_op->op_private & HINT_INTEGER) {
+       IBW i = TOPi;
+       i = BWi(i) >> shift;
+       SETi(BWi(i));
+      }
+      else {
+       UBW u = TOPu;
+       u >>= shift;
+       SETu(BWu(u));
+      }
       RETURN;
     }
 }
@@ -1287,10 +1330,14 @@ PP(pp_bit_and)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (PL_op->op_private & HINT_INTEGER)
-         SETi( SvIV(left) & SvIV(right) );
-       else
-         SETu( SvUV(left) & SvUV(right) );
+       if (PL_op->op_private & HINT_INTEGER) {
+         IBW value = SvIV(left) & SvIV(right);
+         SETi(BWi(value));
+       }
+       else {
+         UBW value = SvUV(left) & SvUV(right);
+         SETu(BWu(value));
+       }
       }
       else {
        do_vop(PL_op->op_type, TARG, left, right);
@@ -1306,10 +1353,14 @@ PP(pp_bit_xor)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (PL_op->op_private & HINT_INTEGER)
-         SETi( (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right) );
-       else
-         SETu( (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right) );
+       if (PL_op->op_private & HINT_INTEGER) {
+         IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
+         SETi(BWi(value));
+       }
+       else {
+         UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
+         SETu(BWu(value));
+       }
       }
       else {
        do_vop(PL_op->op_type, TARG, left, right);
@@ -1325,10 +1376,14 @@ PP(pp_bit_or)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (PL_op->op_private & HINT_INTEGER)
-         SETi( (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right) );
-       else
-         SETu( (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right) );
+       if (PL_op->op_private & HINT_INTEGER) {
+         IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
+         SETi(BWi(value));
+       }
+       else {
+         UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
+         SETu(BWu(value));
+       }
       }
       else {
        do_vop(PL_op->op_type, TARG, left, right);
@@ -1387,10 +1442,14 @@ PP(pp_complement)
     {
       dTOPss;
       if (SvNIOKp(sv)) {
-       if (PL_op->op_private & HINT_INTEGER)
-         SETi( ~SvIV(sv) );
-       else
-         SETu( ~SvUV(sv) );
+       if (PL_op->op_private & HINT_INTEGER) {
+         IBW value = ~SvIV(sv);
+         SETi(BWi(value));
+       }
+       else {
+         UBW value = ~SvUV(sv);
+         SETu(BWu(value));
+       }
       }
       else {
        register char *tmps;
@@ -1719,9 +1778,9 @@ S_seed(pTHX)
 #  endif
 #endif
     u += SEED_C3 * (U32)getpid();
-    u += SEED_C4 * (U32)(UV)PL_stack_sp;
+    u += SEED_C4 * (U32)PTR2UV(PL_stack_sp);
 #ifndef PLAN9           /* XXX Plan9 assembler chokes on this; fix needed  */
-    u += SEED_C5 * (U32)(UV)&when;
+    u += SEED_C5 * (U32)PTR2UV(&when);
 #endif
     return u;
 }
@@ -4870,6 +4929,7 @@ PP(pp_split)
        else {
            if (!AvREAL(ary)) {
                AvREAL_on(ary);
+               AvREIFY_off(ary);
                for (i = AvFILLp(ary); i >= 0; i--)
                    AvARRAY(ary)[i] = &PL_sv_undef;     /* don't free mere refs */
            }