This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Text mode wrongly set on pipe file descriptors
[perl5.git] / util.c
diff --git a/util.c b/util.c
index 88e7812..c5f69ae 100644 (file)
--- a/util.c
+++ b/util.c
@@ -454,8 +454,6 @@ Perl_rninstr(pTHX_ register const char *big, const char *bigend, const char *lit
     return NULL;
 }
 
-#define FBM_TABLE_OFFSET 2     /* Number of bytes between EOS and table*/
-
 /* As a space optimization, we do not compile tables for strings of length
    0 and 1, and for strings of length 2 unless FBMcf_TAIL.  These are
    special-cased in fbm_instr().
@@ -490,19 +488,21 @@ Perl_fbm_compile(pTHX_ SV *sv, U32 flags)
            mg->mg_len++;
     }
     s = (U8*)SvPV_force_mutable(sv, len);
-    SvUPGRADE(sv, SVt_PVBM);
     if (len == 0)              /* TAIL might be on a zero-length string. */
        return;
+    SvUPGRADE(sv, SVt_PVGV);
+    SvIOK_off(sv);
     if (len > 2) {
        const unsigned char *sb;
        const U8 mlen = (len>255) ? 255 : (U8)len;
        register U8 *table;
 
-       Sv_Grow(sv, len + 256 + FBM_TABLE_OFFSET);
-       table = (unsigned char*)(SvPVX_mutable(sv) + len + FBM_TABLE_OFFSET);
-       s = table - 1 - FBM_TABLE_OFFSET;       /* last char */
+       Sv_Grow(sv, len + 256 + PERL_FBM_TABLE_OFFSET);
+       table
+           = (unsigned char*)(SvPVX_mutable(sv) + len + PERL_FBM_TABLE_OFFSET);
+       s = table - 1 - PERL_FBM_TABLE_OFFSET;  /* last char */
        memset((void*)table, mlen, 256);
-       table[-1] = (U8)flags;
+       table[PERL_FBM_FLAGS_OFFSET_FROM_TABLE] = (U8)flags;
        i = 0;
        sb = s - mlen + 1;                      /* first char (maybe) */
        while (s >= sb) {
@@ -510,6 +510,8 @@ Perl_fbm_compile(pTHX_ SV *sv, U32 flags)
                table[*s] = (U8)i;
            s--, i++;
        }
+    } else {
+       Sv_Grow(sv, len + PERL_FBM_TABLE_OFFSET);
     }
     sv_magic(sv, NULL, PERL_MAGIC_bm, NULL, 0);        /* deep magic */
     SvVALID_on(sv);
@@ -522,7 +524,7 @@ Perl_fbm_compile(pTHX_ SV *sv, U32 flags)
        }
     }
     BmRARE(sv) = s[rarest];
-    BmPREVIOUS(sv) = (U16)rarest;
+    BmPREVIOUS_set(sv, rarest);
     BmUSEFUL(sv) = 100;                        /* Initial value */
     if (flags & FBMcf_TAIL)
        SvTAIL_on(sv);
@@ -663,7 +665,7 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
        }
        return NULL;
     }
-    if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
+    if (!SvVALID(littlestr)) {
        char * const b = ninstr((char*)big,(char*)bigend,
                         (char*)little, (char*)little + littlelen);
 
@@ -680,12 +682,15 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
        return b;
     }
 
-    {  /* Do actual FBM.  */
-       register const unsigned char * const table = little + littlelen + FBM_TABLE_OFFSET;
+    /* Do actual FBM.  */
+    if (littlelen > (STRLEN)(bigend - big))
+       return NULL;
+
+    {
+       register const unsigned char * const table
+           = little + littlelen + PERL_FBM_TABLE_OFFSET;
        register const unsigned char *oldlittle;
 
-       if (littlelen > (STRLEN)(bigend - big))
-           return NULL;
        --littlelen;                    /* Last char found by table lookup */
 
        s = big + littlelen;
@@ -718,7 +723,8 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
            }
        }
       check_end:
-       if ( s == bigend && (table[-1] & FBMcf_TAIL)
+       if ( s == bigend
+            && (table[PERL_FBM_FLAGS_OFFSET_FROM_TABLE] & FBMcf_TAIL)
             && memEQ((char *)(bigend - littlelen),
                      (char *)(oldlittle - littlelen), littlelen) )
            return (char*)bigend - littlelen;
@@ -754,12 +760,15 @@ Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift
     register const unsigned char *littleend;
     I32 found = 0;
 
+    assert(SvTYPE(littlestr) == SVt_PVGV);
+    assert(SvVALID(littlestr));
+
     if (*old_posp == -1
        ? (pos = PL_screamfirst[BmRARE(littlestr)]) < 0
        : (((pos = *old_posp), pos += PL_screamnext[pos]) == 0)) {
       cant_find:
        if ( BmRARE(littlestr) == '\n'
-            && BmPREVIOUS(littlestr) == SvCUR(littlestr) - 1) {
+            && BmPREVIOUS(littlestr) == (U8)SvCUR(littlestr) - 1) {
            little = (const unsigned char *)(SvPVX_const(littlestr));
            littleend = little + SvCUR(littlestr);
            first = *little++;
@@ -1556,8 +1565,9 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
    Copy(val, s+(nlen+1), vlen, char); \
    *(s+(nlen+1+vlen)) = '\0'
 
-#if defined(USE_ENVIRON_ARRAY) && !defined(WIN32) && !defined(NETWARE)
-/* VMS' my_setenv() is in vms.c */
+#ifdef USE_ENVIRON_ARRAY
+       /* VMS' my_setenv() is in vms.c */
+#if !defined(WIN32) && !defined(NETWARE)
 void
 Perl_my_setenv(pTHX_ const char *nam, const char *val)
 {
@@ -1569,55 +1579,49 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
   {
 #ifndef PERL_USE_SAFE_PUTENV
     if (!PL_use_safe_putenv) {
-       /* The excuse for this code was that many putenv()s used to
-        * leak, so we manipulate environ directly -- but the claim is
-        * somewhat doubtful, since manipulating environment CANNOT be
-        * made in a safe way, the env API and the whole concept are
-        * fundamentally broken. */
-       register I32 i = setenv_getix(nam);             /* where does it go? */
-       int nlen, vlen;
-
-       if (i >= 0) {
-           if (environ == PL_origenviron) {    /* need we copy environment? */
-               I32 j;
-               I32 max;
-               char **tmpenv;
-           
-               max = i;
-               while (environ[max])
-                   max++;
-               tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
-               for (j=0; j<max; j++) {         /* copy environment */
-                   const int len = strlen(environ[j]);
-                   tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
-                   Copy(environ[j], tmpenv[j], len+1, char);
-               }
-               tmpenv[max] = NULL;
-               environ = tmpenv;               /* tell exec where it is now */
-           }
-           if (!val) {
-               safesysfree(environ[i]);
-               while (environ[i]) {
-                   environ[i] = environ[i+1];
-                   i++;
-               }
-               return;
-           }
-           if (!environ[i]) {                  /* does not exist yet */
-               environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
-               environ[i+1] = NULL;    /* make sure it's null terminated */
-           }
-           else
-               safesysfree(environ[i]);
-           nlen = strlen(nam);
-           vlen = strlen(val);
-           
-           environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
-           /* all that work just for this */
-           my_setenv_format(environ[i], nam, nlen, val, vlen);
+    /* most putenv()s leak, so we manipulate environ directly */
+    register I32 i=setenv_getix(nam);          /* where does it go? */
+    int nlen, vlen;
+
+    if (environ == PL_origenviron) {   /* need we copy environment? */
+       I32 j;
+       I32 max;
+       char **tmpenv;
+
+       max = i;
+       while (environ[max])
+           max++;
+       tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
+       for (j=0; j<max; j++) {         /* copy environment */
+           const int len = strlen(environ[j]);
+           tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
+           Copy(environ[j], tmpenv[j], len+1, char);
+       }
+       tmpenv[max] = NULL;
+       environ = tmpenv;               /* tell exec where it is now */
+    }
+    if (!val) {
+       safesysfree(environ[i]);
+       while (environ[i]) {
+           environ[i] = environ[i+1];
+           i++;
        }
+       return;
+    }
+    if (!environ[i]) {                 /* does not exist yet */
+       environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
+       environ[i+1] = NULL;    /* make sure it's null terminated */
+    }
+    else
+       safesysfree(environ[i]);
+       nlen = strlen(nam);
+       vlen = strlen(val);
+
+       environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
+       /* all that work just for this */
+       my_setenv_format(environ[i], nam, nlen, val, vlen);
     } else {
-#endif
+# endif
 #   if defined(__CYGWIN__) || defined(EPOC) || defined(__SYMBIAN32__) || defined(__riscos__)
 #       if defined(HAS_UNSETENV)
         if (val == NULL) {
@@ -1660,46 +1664,36 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
   }
 }
 
-#else /* defined(USE_ENVIRON_ARRAY) && !defined(WIN32) && !defined(NETWARE)*/
+#else /* WIN32 || NETWARE */
 
 void
 Perl_my_setenv(pTHX_ const char *nam, const char *val)
 {
     dVAR;
-#if !(defined(WIN32) || defined(NETWARE))
-# ifdef USE_ITHREADS
-    /* only parent thread can modify process environment */
-    if (PL_curinterp == aTHX)
-# endif
-#endif
-    {
-       register char *envstr;
-       const int nlen = strlen(nam);
-       int vlen;
+    register char *envstr;
+    const int nlen = strlen(nam);
+    int vlen;
 
-       if (!val) {
-           val = "";
-       }
-       vlen = strlen(val);
-       Newx(envstr, nlen+vlen+2, char);
-       my_setenv_format(envstr, nam, nlen, val, vlen);
-       (void)PerlEnv_putenv(envstr);
-       Safefree(envstr);
+    if (!val) {
+       val = "";
     }
+    vlen = strlen(val);
+    Newx(envstr, nlen+vlen+2, char);
+    my_setenv_format(envstr, nam, nlen, val, vlen);
+    (void)PerlEnv_putenv(envstr);
+    Safefree(envstr);
 }
 
-#endif /* defined(USE_ENVIRON_ARRAY) && !defined(WIN32) && !defined(NETWARE) */
-
-#if !defined(VMS)
+#endif /* WIN32 || NETWARE */
 
+#ifndef PERL_MICRO
 I32
 Perl_setenv_getix(pTHX_ const char *nam)
 {
-    register I32 i = -1;
+    register I32 i;
     register const I32 len = strlen(nam);
     PERL_UNUSED_CONTEXT;
 
-#ifdef USE_ENVIRON_ARRAY
     for (i = 0; environ[i]; i++) {
        if (
 #ifdef WIN32
@@ -1710,12 +1704,11 @@ Perl_setenv_getix(pTHX_ const char *nam)
            && environ[i][len] == '=')
            break;                      /* strnEQ must come first to avoid */
     }                                  /* potential SEGV's */
-#endif /* USE_ENVIRON_ARRAY */
-
     return i;
 }
+#endif /* !PERL_MICRO */
 
-#endif /* !PERL_VMS */
+#endif /* !VMS && !EPOC*/
 
 #ifdef UNLINK_ALL_VERSIONS
 I32
@@ -2363,6 +2356,14 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
            PerlProc__exit(1);
        }
 #endif /* defined OS2 */
+
+#ifdef PERLIO_USING_CRLF
+   /* Since we circumvent IO layers when we manipulate low-level
+      filedescriptors directly, need to manually switch to the
+      default, binary, low-level mode; see PerlIOBuf_open(). */
+   PerlLIO_setmode((*mode == 'r'), O_BINARY);
+#endif 
+
        if ((tmpgv = gv_fetchpvs("$", GV_ADD|GV_NOTQUAL, SVt_PV))) {
            SvREADONLY_off(GvSV(tmpgv));
            sv_setiv(GvSV(tmpgv), PerlProc_getpid());
@@ -2431,7 +2432,7 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
 #if defined(atarist) || defined(EPOC)
 FILE *popen();
 PerlIO *
-Perl_my_popen(pTHX_ char *cmd, char *mode)
+Perl_my_popen((pTHX_ const char *cmd, const char *mode)
 {
     PERL_FLUSHALL_FOR_CHILD;
     /* Call system's popen() to get a FILE *, then import it.
@@ -2444,7 +2445,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
 #if defined(DJGPP)
 FILE *djgpp_popen();
 PerlIO *
-Perl_my_popen(pTHX_ char *cmd, char *mode)
+Perl_my_popen((pTHX_ const char *cmd, const char *mode)
 {
     PERL_FLUSHALL_FOR_CHILD;
     /* Call system's popen() to get a FILE *, then import it.
@@ -3845,7 +3846,7 @@ Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, in
   else {
     /* Possibly buf overflowed - try again with a bigger buf */
     const int fmtlen = strlen(fmt);
-    const int bufsize = fmtlen + buflen;
+    int bufsize = fmtlen + buflen;
 
     Newx(buf, bufsize, char);
     while (buf) {
@@ -3858,7 +3859,8 @@ Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, in
        buf = NULL;
        break;
       }
-      Renew(buf, bufsize*2, char);
+      bufsize *= 2;
+      Renew(buf, bufsize, char);
     }
     return buf;
   }
@@ -4319,7 +4321,13 @@ Perl_upg_version(pTHX_ SV *ver)
     if ( SvNOK(ver) ) /* may get too much accuracy */ 
     {
        char tbuf[64];
+#ifdef USE_LOCALE_NUMERIC
+       char *loc = setlocale(LC_NUMERIC, "C");
+#endif
        STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVff, SvNVX(ver));
+#ifdef USE_LOCALE_NUMERIC
+       setlocale(LC_NUMERIC, loc);
+#endif
        while (tbuf[len-1] == '0' && len > 0) len--;
        version = savepvn(tbuf, len);
     }
@@ -5485,7 +5493,7 @@ Perl_my_clearenv(pTHX)
     char *buf = (char*)safesysmalloc(bufsiz);
     while (*environ != NULL) {
       char *e = strchr(*environ, '=');
-      int l = e ? e - *environ : strlen(*environ);
+      int l = e ? e - *environ : (int)strlen(*environ);
       if (bsiz < l + 1) {
         (void)safesysfree(buf);
         bsiz = l + 1; /* + 1 for the \0. */
@@ -5580,6 +5588,42 @@ Perl_my_strlcpy(char *dst, const char *src, Size_t size)
 }
 #endif
 
+void
+Perl_get_db_sub(pTHX_ SV **svp, CV *cv)
+{
+    dVAR;
+    SV * const dbsv = GvSVn(PL_DBsub);
+    /* We do not care about using sv to call CV;
+     * it's for informational purposes only.
+     */
+
+    save_item(dbsv);
+    if (!PERLDB_SUB_NN) {
+       GV * const gv = CvGV(cv);
+
+       if ( svp && ((CvFLAGS(cv) & (CVf_ANON | CVf_CLONED))
+            || strEQ(GvNAME(gv), "END")
+            || ((GvCV(gv) != cv) && /* Could be imported, and old sub redefined. */
+                !( (SvTYPE(*svp) == SVt_PVGV) && (GvCV((GV*)*svp) == cv) )))) {
+           /* Use GV from the stack as a fallback. */
+           /* GV is potentially non-unique, or contain different CV. */
+           SV * const tmp = newRV((SV*)cv);
+           sv_setsv(dbsv, tmp);
+           SvREFCNT_dec(tmp);
+       }
+       else {
+           gv_efullname3(dbsv, gv, NULL);
+       }
+    }
+    else {
+       const int type = SvTYPE(dbsv);
+       if (type < SVt_PVIV && type != SVt_IV)
+           sv_upgrade(dbsv, SVt_PVIV);
+       (void)SvIOK_on(dbsv);
+       SvIV_set(dbsv, PTR2IV(cv));     /* Do it the quickest way  */
+    }
+}
+
 /*
  * Local variables:
  * c-indentation-style: bsd