#2026 fallout.
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index a4f7828..9d9ad5c 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1560,11 +1560,13 @@ PP(pp_cos)
    compatibility by calling rand() but allow the user to override it.
    See INSTALL for details.  --Andy Dougherty  15 July 1998
 */
-#ifndef my_rand
-#  define my_rand      rand
-#endif
-#ifndef my_srand
-#  define my_srand     srand
+/* Now it's after 5.005, and Configure supports drand48() and random(),
+   in addition to rand().  So the overrides should not be needed any more.
+   --Jarkko Hietaniemi 27 September 1998
+ */
+
+#ifndef HAS_DRAND48_PROTO
+extern double drand48 _((void));
 #endif
 
 PP(pp_rand)
@@ -1578,22 +1580,10 @@ PP(pp_rand)
     if (value == 0.0)
        value = 1.0;
     if (!srand_called) {
-       (void)my_srand((unsigned)seed());
+       (void)seedDrand01((Rand_seed_t)seed());
        srand_called = TRUE;
     }
-#if RANDBITS == 31
-    value = my_rand() * value / 2147483648.0;
-#else
-#if RANDBITS == 16
-    value = my_rand() * value / 65536.0;
-#else
-#if RANDBITS == 15
-    value = my_rand() * value / 32768.0;
-#else
-    value = my_rand() * value / (double)(((unsigned long)1) << RANDBITS);
-#endif
-#endif
-#endif
+    value *= Drand01();
     XPUSHn(value);
     RETURN;
 }
@@ -1606,7 +1596,7 @@ PP(pp_srand)
        anum = seed();
     else
        anum = POPu;
-    (void)my_srand((unsigned)anum);
+    (void)seedDrand01((Rand_seed_t)anum);
     srand_called = TRUE;
     EXTEND(SP, 1);
     RETPUSHYES;
@@ -1619,9 +1609,9 @@ seed(void)
      * 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.
+     * if someone who knows about such things 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,
+     * No numbers below come from careful analysis or anything 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.
@@ -1638,21 +1628,50 @@ seed(void)
 #define   SEED_C5      26107
 
     dTHR;
+#ifndef PERL_NO_DEV_RANDOM
+    int fd;
+#endif
     U32 u;
 #ifdef VMS
 #  include <starlet.h>
     /* when[] = (low 32 bits, high 32 bits) of time since epoch
      * in 100-ns units, typically incremented ever 10 ms.        */
     unsigned int when[2];
+#else
+#  ifdef HAS_GETTIMEOFDAY
+    struct timeval when;
+#  else
+    Time_t when;
+#  endif
+#endif
+
+/* This test is an escape hatch, this symbol isn't set by Configure. */
+#ifndef PERL_NO_DEV_RANDOM
+#ifndef PERL_RANDOM_DEVICE
+   /* /dev/random isn't used by default because reads from it will block
+    * if there isn't enough entropy available.  You can compile with
+    * PERL_RANDOM_DEVICE to it if you'd prefer Perl to block until there
+    * is enough real entropy to fill the seed. */
+#  define PERL_RANDOM_DEVICE "/dev/urandom"
+#endif
+    fd = PerlLIO_open(PERL_RANDOM_DEVICE, 0);
+    if (fd != -1) {
+       if (PerlLIO_read(fd, &u, sizeof u) != sizeof u)
+           u = 0;
+       PerlLIO_close(fd);
+       if (u)
+           return u;
+    }
+#endif
+
+#ifdef VMS
     _ckvmssts(sys$gettim(when));
     u = (U32)SEED_C1 * when[0] + (U32)SEED_C2 * when[1];
 #else
 #  ifdef HAS_GETTIMEOFDAY
-    struct timeval when;
     gettimeofday(&when,(struct timezone *) 0);
     u = (U32)SEED_C1 * when.tv_sec + (U32)SEED_C2 * when.tv_usec;
 #  else
-    Time_t when;
     (void)time(&when);
     u = (U32)SEED_C1 * when;
 #  endif
@@ -3397,7 +3416,10 @@ PP(pp_unpack)
                while (len-- > 0 && s < strend) {
                    auint = utf8_to_uv((U8*)s, &along);
                    s += along;
-                   culong += auint;
+                   if (checksum > 32)
+                       cdouble += (double)auint;
+                   else
+                       culong += auint;
                }
            }
            else {
@@ -3798,7 +3820,7 @@ PP(pp_unpack)
                char hunk[4];
 
                hunk[3] = '\0';
-               len = (*s++ - ' ') & 077;
+               len = uudmap[*s++] & 077;
                while (len > 0) {
                    if (s < strend && ISUUCHAR(*s))
                        a = uudmap[*s++] & 077;
@@ -3833,7 +3855,7 @@ PP(pp_unpack)
        if (checksum) {
            sv = NEWSV(42, 0);
            if (strchr("fFdD", datumtype) ||
-             (checksum > 32 && strchr("iIlLN", datumtype)) ) {
+             (checksum > 32 && strchr("iIlLNU", datumtype)) ) {
                double trouble;
 
                adouble = 1.0;