This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Regenerate perlapi and perltoc.
[perl5.git] / util.c
diff --git a/util.c b/util.c
index 1f1c6fc..4a1a45f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,6 +1,7 @@
 /*    util.c
  *
- *    Copyright (c) 1991-2003, Larry Wall
+ *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ *    2000, 2001, 2002, 2003, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -976,6 +977,52 @@ Perl_vmess(pTHX_ const char *pat, va_list *args)
     return sv;
 }
 
+void
+Perl_write_to_stderr(pTHX_ const char* message, int msglen)
+{
+    IO *io;
+    MAGIC *mg;
+
+    if (PL_stderrgv && SvREFCNT(PL_stderrgv) 
+       && (io = GvIO(PL_stderrgv))
+       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) 
+    {
+       dSP;
+       ENTER;
+       SAVETMPS;
+
+       save_re_context();
+       SAVESPTR(PL_stderrgv);
+       PL_stderrgv = Nullgv;
+
+       PUSHSTACKi(PERLSI_MAGIC);
+
+       PUSHMARK(SP);
+       EXTEND(SP,2);
+       PUSHs(SvTIED_obj((SV*)io, mg));
+       PUSHs(sv_2mortal(newSVpvn(message, msglen)));
+       PUTBACK;
+       call_method("PRINT", G_SCALAR);
+
+       POPSTACK;
+       FREETMPS;
+       LEAVE;
+    }
+    else {
+#ifdef USE_SFIO
+       /* SFIO can really mess with your errno */
+       int e = errno;
+#endif
+       PerlIO *serr = Perl_error_log;
+
+       PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
+       (void)PerlIO_flush(serr);
+#ifdef USE_SFIO
+       errno = e;
+#endif
+    }
+}
+
 OP *
 Perl_vdie(pTHX_ const char* pat, va_list *args)
 {
@@ -986,6 +1033,7 @@ Perl_vdie(pTHX_ const char* pat, va_list *args)
     CV *cv;
     SV *msv;
     STRLEN msglen;
+    I32 utf8 = 0;
 
     DEBUG_S(PerlIO_printf(Perl_debug_log,
                          "%p: die: curstack = %p, mainstack = %p\n",
@@ -1000,6 +1048,7 @@ Perl_vdie(pTHX_ const char* pat, va_list *args)
        }
        else
            message = SvPV(msv,msglen);
+       utf8 = SvUTF8(msv);
     }
     else {
        message = Nullch;
@@ -1025,6 +1074,7 @@ Perl_vdie(pTHX_ const char* pat, va_list *args)
            save_re_context();
            if (message) {
                msg = newSVpvn(message, msglen);
+               SvFLAGS(msg) |= utf8;
                SvREADONLY_on(msg);
                SAVEFREESV(msg);
            }
@@ -1043,6 +1093,7 @@ Perl_vdie(pTHX_ const char* pat, va_list *args)
     }
 
     PL_restartop = die_where(message, msglen);
+    SvFLAGS(ERRSV) |= utf8;
     DEBUG_S(PerlIO_printf(Perl_debug_log,
          "%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n",
          thr, PL_restartop, was_in_eval, PL_top_env));
@@ -1085,6 +1136,7 @@ Perl_vcroak(pTHX_ const char* pat, va_list *args)
     CV *cv;
     SV *msv;
     STRLEN msglen;
+    I32 utf8 = 0;
 
     if (pat) {
        msv = vmess(pat, args);
@@ -1095,6 +1147,7 @@ Perl_vcroak(pTHX_ const char* pat, va_list *args)
        }
        else
            message = SvPV(msv,msglen);
+       utf8 = SvUTF8(msv);
     }
     else {
        message = Nullch;
@@ -1120,6 +1173,7 @@ Perl_vcroak(pTHX_ const char* pat, va_list *args)
            save_re_context();
            if (message) {
                msg = newSVpvn(message, msglen);
+               SvFLAGS(msg) |= utf8;
                SvREADONLY_on(msg);
                SAVEFREESV(msg);
            }
@@ -1138,24 +1192,13 @@ Perl_vcroak(pTHX_ const char* pat, va_list *args)
     }
     if (PL_in_eval) {
        PL_restartop = die_where(message, msglen);
+       SvFLAGS(ERRSV) |= utf8;
        JMPENV_JUMP(3);
     }
     else if (!message)
        message = SvPVx(ERRSV, msglen);
 
-    {
-#ifdef USE_SFIO
-       /* SFIO can really mess with your errno */
-       int e = errno;
-#endif
-       PerlIO *serr = Perl_error_log;
-
-       PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
-       (void)PerlIO_flush(serr);
-#ifdef USE_SFIO
-       errno = e;
-#endif
-    }
+    write_to_stderr(message, msglen);
     my_failure_exit();
 }
 
@@ -1210,10 +1253,10 @@ Perl_vwarn(pTHX_ const char* pat, va_list *args)
     CV *cv;
     SV *msv;
     STRLEN msglen;
-    IO *io;
-    MAGIC *mg;
+    I32 utf8 = 0;
 
     msv = vmess(pat, args);
+    utf8 = SvUTF8(msv);
     message = SvPV(msv, msglen);
 
     if (PL_warnhook) {
@@ -1231,6 +1274,7 @@ Perl_vwarn(pTHX_ const char* pat, va_list *args)
            ENTER;
            save_re_context();
            msg = newSVpvn(message, msglen);
+           SvFLAGS(msg) |= utf8;
            SvREADONLY_on(msg);
            SAVEFREESV(msg);
 
@@ -1245,25 +1289,7 @@ Perl_vwarn(pTHX_ const char* pat, va_list *args)
        }
     }
 
-    /* if STDERR is tied, use it instead */
-    if (PL_stderrgv && (io = GvIOp(PL_stderrgv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
-       dSP; ENTER;
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       XPUSHs(sv_2mortal(newSVpvn(message, msglen)));
-       PUTBACK;
-       call_method("PRINT", G_SCALAR);
-       LEAVE;
-       return;
-    }
-
-    {
-       PerlIO *serr = Perl_error_log;
-
-       PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
-       (void)PerlIO_flush(serr);
-    }
+    write_to_stderr(message, msglen);
 }
 
 #if defined(PERL_IMPLICIT_CONTEXT)
@@ -1327,9 +1353,11 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
     CV *cv;
     SV *msv;
     STRLEN msglen;
+    I32 utf8 = 0;
 
     msv = vmess(pat, args);
     message = SvPV(msv, msglen);
+    utf8 = SvUTF8(msv);
 
     if (ckDEAD(err)) {
        if (PL_diehook) {
@@ -1347,6 +1375,7 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
                ENTER;
                save_re_context();
                msg = newSVpvn(message, msglen);
+               SvFLAGS(msg) |= utf8;
                SvREADONLY_on(msg);
                SAVEFREESV(msg);
 
@@ -1361,13 +1390,10 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
        }
        if (PL_in_eval) {
            PL_restartop = die_where(message, msglen);
+           SvFLAGS(ERRSV) |= utf8;
            JMPENV_JUMP(3);
        }
-       {
-           PerlIO *serr = Perl_error_log;
-           PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
-           (void)PerlIO_flush(serr);
-       }
+       write_to_stderr(message, msglen);
        my_failure_exit();
     }
     else {
@@ -1386,6 +1412,7 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
                ENTER;
                save_re_context();
                msg = newSVpvn(message, msglen);
+               SvFLAGS(msg) |= utf8;
                SvREADONLY_on(msg);
                SAVEFREESV(msg);
 
@@ -1399,11 +1426,7 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
                return;
            }
        }
-       {
-           PerlIO *serr = Perl_error_log;
-           PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
-           (void)PerlIO_flush(serr);
-       }
+       write_to_stderr(message, msglen);
     }
 }
 
@@ -1509,6 +1532,7 @@ Perl_my_setenv(pTHX_ char *nam,char *val)
 
 #endif /* WIN32 || NETWARE */
 
+#ifndef PERL_MICRO
 I32
 Perl_setenv_getix(pTHX_ char *nam)
 {
@@ -1526,6 +1550,7 @@ Perl_setenv_getix(pTHX_ char *nam)
     }                                  /* potential SEGV's */
     return i;
 }
+#endif /* !PERL_MICRO */
 
 #endif /* !VMS && !EPOC*/
 
@@ -2199,7 +2224,7 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
     if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
         act.sa_flags |= SA_RESTART;    /* SVR4, 4.3+BSD */
 #endif
-#ifdef SA_NOCLDWAIT
+#if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
     if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
        act.sa_flags |= SA_NOCLDWAIT;
 #endif
@@ -2238,7 +2263,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
     if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
         act.sa_flags |= SA_RESTART;    /* SVR4, 4.3+BSD */
 #endif
-#ifdef SA_NOCLDWAIT
+#if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
     if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
        act.sa_flags |= SA_NOCLDWAIT;
 #endif
@@ -3627,85 +3652,6 @@ Perl_getcwd_sv(pTHX_ register SV *sv)
 }
 
 /*
-=head1 SV Manipulation Functions
-
-=for apidoc scan_vstring
-
-Returns a pointer to the next character after the parsed
-vstring, as well as updating the passed in sv.
-
-Function must be called like
-
-       sv = NEWSV(92,5);
-       s = scan_vstring(s,sv);
-
-The sv should already be large enough to store the vstring
-passed in, for performance reasons.
-
-=cut
-*/
-
-char *
-Perl_scan_vstring(pTHX_ char *s, SV *sv)
-{
-    char *pos = s;
-    char *start = s;
-    if (*pos == 'v') pos++;  /* get past 'v' */
-    while (isDIGIT(*pos) || *pos == '_')
-    pos++;
-    if (!isALPHA(*pos)) {
-       UV rev;
-       U8 tmpbuf[UTF8_MAXLEN+1];
-       U8 *tmpend;
-
-       if (*s == 'v') s++;  /* get past 'v' */
-
-       sv_setpvn(sv, "", 0);
-
-       for (;;) {
-           rev = 0;
-           {
-               /* this is atoi() that tolerates underscores */
-               char *end = pos;
-               UV mult = 1;
-               while (--end >= s) {
-                   UV orev;
-                   if (*end == '_')
-                       continue;
-                   orev = rev;
-                   rev += (*end - '0') * mult;
-                   mult *= 10;
-                   if (orev > rev && ckWARN_d(WARN_OVERFLOW))
-                       Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
-                                   "Integer overflow in decimal number");
-               }
-           }
-#ifdef EBCDIC
-           if (rev > 0x7FFFFFFF)
-                Perl_croak(aTHX "In EBCDIC the v-string components cannot exceed 2147483647");
-#endif
-           /* Append native character for the rev point */
-           tmpend = uvchr_to_utf8(tmpbuf, rev);
-           sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
-           if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
-                SvUTF8_on(sv);
-           if (*pos == '.' && isDIGIT(pos[1]))
-                s = ++pos;
-           else {
-                s = pos;
-                break;
-           }
-           while (isDIGIT(*pos) || *pos == '_')
-                pos++;
-       }
-       SvPOK_on(sv);
-       sv_magic(sv,NULL,PERL_MAGIC_vstring,(const char*)start, pos-start);
-       SvRMAGICAL_on(sv);
-    }
-    return s;
-}
-
-/*
 =for apidoc scan_version
 
 Returns a pointer to the next character after the parsed
@@ -4368,3 +4314,120 @@ Perl_parse_unicode_opts(pTHX_ char **popt)
   return opt;
 }
 
+U32
+Perl_seed(pTHX)
+{
+    /*
+     * 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 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 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.
+     */
+#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
+
+#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
+    PerlProc_gettimeofday(&when,NULL);
+    u = (U32)SEED_C1 * when.tv_sec + (U32)SEED_C2 * when.tv_usec;
+#  else
+    (void)time(&when);
+    u = (U32)SEED_C1 * when;
+#  endif
+#endif
+    u += SEED_C3 * (U32)PerlProc_getpid();
+    u += SEED_C4 * (U32)PTR2UV(PL_stack_sp);
+#ifndef PLAN9           /* XXX Plan9 assembler chokes on this; fix needed  */
+    u += SEED_C5 * (U32)PTR2UV(&when);
+#endif
+    return u;
+}
+
+UV
+Perl_get_hash_seed(pTHX)
+{
+     char *s = PerlEnv_getenv("PERL_HASH_SEED");
+     UV myseed = 0;
+
+     if (s)
+         while (isSPACE(*s)) s++;
+     if (s && isDIGIT(*s))
+         myseed = (UV)Atoul(s);
+     else
+#ifdef USE_HASH_SEED_EXPLICIT
+     if (s)
+#endif
+     {
+         /* Compute a random seed */
+         (void)seedDrand01((Rand_seed_t)seed());
+         myseed = (UV)(Drand01() * (NV)UV_MAX);
+#if RANDBITS < (UVSIZE * 8)
+         /* Since there are not enough randbits to to reach all
+          * the bits of a UV, the low bits might need extra
+          * help.  Sum in another random number that will
+          * fill in the low bits. */
+         myseed +=
+              (UV)(Drand01() * (NV)((1 << ((UVSIZE * 8 - RANDBITS))) - 1));
+#endif /* RANDBITS < (UVSIZE * 8) */
+         if (myseed == 0) { /* Superparanoia. */
+             myseed = (UV)(Drand01() * (NV)UV_MAX); /* One more chance. */
+             if (myseed == 0)
+                 Perl_croak(aTHX_ "Your random numbers are not that random");
+         }
+     }
+     PL_rehash_seed_set = TRUE;
+
+     return myseed;
+}