This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [perl #38868] Changing $0 on darwin leads to excessive padding in 'ps'
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index c8c935a..56e8065 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -272,7 +272,7 @@ Perl_mg_length(pTHX_ SV *sv)
 
     if (DO_UTF8(sv)) {
         const U8 *s = (U8*)SvPV_const(sv, len);
 
     if (DO_UTF8(sv)) {
         const U8 *s = (U8*)SvPV_const(sv, len);
-        len = Perl_utf8_length(aTHX_ s, s + len);
+       len = utf8_length(s, s + len);
     }
     else
         (void)SvPV_const(sv, len);
     }
     else
         (void)SvPV_const(sv, len);
@@ -379,7 +379,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
        }
        else {
            const char type = mg->mg_type;
        }
        else {
            const char type = mg->mg_type;
-           if (isUPPER(type)) {
+           if (isUPPER(type) && type != PERL_MAGIC_uvar) {
                sv_magic(nsv,
                     (type == PERL_MAGIC_tied)
                        ? SvTIED_obj(sv, mg)
                sv_magic(nsv,
                     (type == PERL_MAGIC_tied)
                        ? SvTIED_obj(sv, mg)
@@ -497,9 +497,18 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
     if (PL_curpm) {
        register const REGEXP * const rx = PM_GETRE(PL_curpm);
        if (rx) {
     if (PL_curpm) {
        register const REGEXP * const rx = PM_GETRE(PL_curpm);
        if (rx) {
-           return mg->mg_obj
-               ? rx->nparens       /* @+ */
-               : rx->lastparen;    /* @- */
+           if (mg->mg_obj) {                   /* @+ */
+               /* return the number possible */
+               return rx->nparens;
+           } else {                            /* @- */
+               I32 paren = rx->lastparen;
+
+               /* return the last filled */
+               while ( paren >= 0
+                       && (rx->startp[paren] == -1 || rx->endp[paren] == -1) )
+                   paren--;
+               return (U32)paren;
+           }
        }
     }
 
        }
     }
 
@@ -531,7 +540,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
                    if (i > 0 && RX_MATCH_UTF8(rx)) {
                        const char * const b = rx->subbeg;
                        if (b)
                    if (i > 0 && RX_MATCH_UTF8(rx)) {
                        const char * const b = rx->subbeg;
                        if (b)
-                           i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i));
+                           i = utf8_length((U8*)b, (U8*)(b+i));
                    }
 
                    sv_setiv(sv, i);
                    }
 
                    sv_setiv(sv, i);
@@ -758,10 +767,13 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
            SvTAINTED_off(sv);
        }
        else if (strEQ(remaining, "PEN")) {
            SvTAINTED_off(sv);
        }
        else if (strEQ(remaining, "PEN")) {
-           if (!PL_compiling.cop_io)
+           if (!(CopHINTS_get(&PL_compiling) & HINT_LEXICAL_IO))
                sv_setsv(sv, &PL_sv_undef);
             else {
                sv_setsv(sv, &PL_sv_undef);
             else {
-               sv_setsv(sv, PL_compiling.cop_io);
+               sv_setsv(sv,
+                        Perl_refcounted_he_fetch(aTHX_
+                                                 PL_compiling.cop_hints_hash,
+                                                 0, "open", 4, 0, 0));
            }
        }
        break;
            }
        }
        break;
@@ -816,10 +828,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
             else if (PL_compiling.cop_warnings == pWARN_ALL) {
                /* Get the bit mask for $warnings::Bits{all}, because
                 * it could have been extended by warnings::register */
             else if (PL_compiling.cop_warnings == pWARN_ALL) {
                /* Get the bit mask for $warnings::Bits{all}, because
                 * it could have been extended by warnings::register */
-               SV **bits_all;
                HV * const bits=get_hv("warnings::Bits", FALSE);
                HV * const bits=get_hv("warnings::Bits", FALSE);
-               if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) {
-                   sv_setsv(sv, *bits_all);
+               if (bits) {
+                   SV ** const bits_all = hv_fetchs(bits, "all", FALSE);
+                   if (bits_all)
+                       sv_setsv(sv, *bits_all);
                }
                else {
                    sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
                }
                else {
                    sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
@@ -850,6 +863,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                i = t1 - s1;
                s = rx->subbeg + s1;
                assert(rx->subbeg);
                i = t1 - s1;
                s = rx->subbeg + s1;
                assert(rx->subbeg);
+               assert(rx->sublen >= s1);
 
              getrx:
                if (i >= 0) {
 
              getrx:
                if (i >= 0) {
@@ -857,8 +871,13 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                    TAINT_NOT;
                    sv_setpvn(sv, s, i);
                    PL_tainted = oldtainted;
                    TAINT_NOT;
                    sv_setpvn(sv, s, i);
                    PL_tainted = oldtainted;
-                   if (RX_MATCH_UTF8(rx) && is_utf8_string((U8*)s, i))
+                   if ( (rx->extflags & RXf_CANY_SEEN)
+                       ? (RX_MATCH_UTF8(rx)
+                                   && (!i || is_utf8_string((U8*)s, i)))
+                       : (RX_MATCH_UTF8(rx)) )
+                   {
                        SvUTF8_on(sv);
                        SvUTF8_on(sv);
+                   }
                    else
                        SvUTF8_off(sv);
                    if (PL_tainting) {
                    else
                        SvUTF8_off(sv);
                    if (PL_tainting) {
@@ -964,7 +983,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '/':
        break;
     case '[':
     case '/':
        break;
     case '[':
-       WITH_THR(sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop)));
+       sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop));
        break;
     case '|':
        if (GvIOp(PL_defoutgv))
        break;
     case '|':
        if (GvIOp(PL_defoutgv))
@@ -1069,8 +1088,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
            Stat_t sbuf;
            int i = 0, j = 0;
 
            Stat_t sbuf;
            int i = 0, j = 0;
 
-           strncpy(eltbuf, s, 255);
-           eltbuf[255] = 0;
+           my_strlcpy(eltbuf, s, sizeof(eltbuf));
            elt = eltbuf;
            do {          /* DCL$PATH may be a search list */
                while (1) {   /* as may dev portion of any element */
            elt = eltbuf;
            do {          /* DCL$PATH may be a search list */
                while (1) {   /* as may dev portion of any element */
@@ -1099,11 +1117,20 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
                char tmpbuf[256];
                Stat_t st;
                I32 i;
                char tmpbuf[256];
                Stat_t st;
                I32 i;
+#ifdef VMS  /* Hmm.  How do we get $Config{path_sep} from C? */
+               const char path_sep = '|';
+#else
+               const char path_sep = ':';
+#endif
                s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
                s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
-                            s, strend, ':', &i);
+                            s, strend, path_sep, &i);
                s++;
                if (i >= (I32)sizeof tmpbuf   /* too long -- assume the worst */
                s++;
                if (i >= (I32)sizeof tmpbuf   /* too long -- assume the worst */
-                     || *tmpbuf != '/'
+#ifdef VMS
+                     || !strchr(tmpbuf, ':') /* no colon thus no device name -- assume relative path */
+#else
+                     || *tmpbuf != '/'       /* no starting slash -- assume relative path */
+#endif
                      || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
                    MgTAINTEDDIR_on(mg);
                    return 0;
                      || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
                    MgTAINTEDDIR_on(mg);
                    return 0;
@@ -1166,7 +1193,7 @@ static void
 restore_sigmask(pTHX_ SV *save_sv)
 {
     const sigset_t * const ossetp = (const sigset_t *) SvPV_nolen_const( save_sv );
 restore_sigmask(pTHX_ SV *save_sv)
 {
     const sigset_t * const ossetp = (const sigset_t *) SvPV_nolen_const( save_sv );
-    (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
+    (void)sigprocmask(SIG_SETMASK, ossetp, NULL);
 }
 #endif
 int
 }
 #endif
 int
@@ -1212,14 +1239,12 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
        SV** svp = NULL;
        if (strEQ(s,"__DIE__"))
            svp = &PL_diehook;
        SV** svp = NULL;
        if (strEQ(s,"__DIE__"))
            svp = &PL_diehook;
-       else if (strEQ(s,"__WARN__"))
+       else if (strEQ(s,"__WARN__") && PL_warnhook != PERL_WARNHOOK_FATAL)
            svp = &PL_warnhook;
            svp = &PL_warnhook;
-       else
-           Perl_croak(aTHX_ "No such hook: %s", s);
        if (svp && *svp) {
        if (svp && *svp) {
-            SV * const to_dec = *svp;
+           SV *const to_dec = *svp;
            *svp = NULL;
            *svp = NULL;
-           SvREFCNT_dec(to_dec);
+           SvREFCNT_dec(to_dec);
        }
     }
     else {
        }
     }
     else {
@@ -1299,7 +1324,17 @@ Perl_csighandler(int sig)
             exit(1);
 #endif
 #endif
             exit(1);
 #endif
 #endif
-   if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)
+   if (
+#ifdef SIGILL
+          sig == SIGILL ||
+#endif
+#ifdef SIGBUS
+          sig == SIGBUS ||
+#endif
+#ifdef SIGSEGV
+          sig == SIGSEGV ||
+#endif
+          (PL_signals & PERL_SIGNALS_UNSAFE_FLAG))
        /* Call the perl level handler now--
         * with risk we may be in malloc() etc. */
        (*PL_sighandlerp)(sig);
        /* Call the perl level handler now--
         * with risk we may be in malloc() etc. */
        (*PL_sighandlerp)(sig);
@@ -1372,7 +1407,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
            Perl_croak(aTHX_ "No such hook: %s", s);
        i = 0;
        if (*svp) {
            Perl_croak(aTHX_ "No such hook: %s", s);
        i = 0;
        if (*svp) {
-           to_dec = *svp;
+           if (*svp != PERL_WARNHOOK_FATAL)
+               to_dec = *svp;
            *svp = NULL;
        }
     }
            *svp = NULL;
        }
     }
@@ -1423,7 +1459,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
            SvREFCNT_dec(to_dec);
        return 0;
     }
            SvREFCNT_dec(to_dec);
        return 0;
     }
-    s = SvPV_force(sv,len);
+    s = SvOK(sv) ? SvPV_force(sv,len) : "DEFAULT";
     if (strEQ(s,"IGNORE")) {
        if (i) {
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
     if (strEQ(s,"IGNORE")) {
        if (i) {
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
@@ -1659,7 +1695,7 @@ Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
 }
 
 int
 }
 
 int
-Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg)
+Perl_magic_existspack(pTHX_ SV *sv, const MAGIC *mg)
 {
     return magic_methpack(sv,mg,"EXISTS");
 }
 {
     return magic_methpack(sv,mg,"EXISTS");
 }
@@ -2230,10 +2266,11 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            }
        }
        else if (strEQ(mg->mg_ptr, "\017PEN")) {
            }
        }
        else if (strEQ(mg->mg_ptr, "\017PEN")) {
-           if (!PL_compiling.cop_io)
-               PL_compiling.cop_io = newSVsv(sv);
-           else
-               sv_setsv(PL_compiling.cop_io,sv);
+           PL_compiling.cop_hints |= HINT_LEXICAL_IO;
+           PL_hints |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO;
+           PL_compiling.cop_hints_hash
+               = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
+                                        sv_2mortal(newSVpvs("open")), sv);
        }
        break;
     case '\020':       /* ^P */
        }
        break;
     case '\020':       /* ^P */
@@ -2277,11 +2314,16 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                        accumulate |= ptr[i] ;
                        any_fatals |= (ptr[i] & 0xAA) ;
                    }
                        accumulate |= ptr[i] ;
                        any_fatals |= (ptr[i] & 0xAA) ;
                    }
-                   if (!accumulate)
-                       PL_compiling.cop_warnings = pWARN_NONE;
+                   if (!accumulate) {
+                       if (!specialWARN(PL_compiling.cop_warnings))
+                           PerlMemShared_free(PL_compiling.cop_warnings);
+                       PL_compiling.cop_warnings = pWARN_NONE;
+                   }
                    /* Yuck. I can't see how to abstract this:  */
                    else if (isWARN_on(((STRLEN *)SvPV_nolen_const(sv)) - 1,
                                       WARN_ALL) && !any_fatals) {
                    /* Yuck. I can't see how to abstract this:  */
                    else if (isWARN_on(((STRLEN *)SvPV_nolen_const(sv)) - 1,
                                       WARN_ALL) && !any_fatals) {
+                       if (!specialWARN(PL_compiling.cop_warnings))
+                           PerlMemShared_free(PL_compiling.cop_warnings);
                        PL_compiling.cop_warnings = pWARN_ALL;
                        PL_dowarn |= G_WARN_ONCE ;
                    }
                        PL_compiling.cop_warnings = pWARN_ALL;
                        PL_dowarn |= G_WARN_ONCE ;
                    }
@@ -2510,8 +2552,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
             }
             if (i)
                 (void)setgroups(i, gary);
             }
             if (i)
                 (void)setgroups(i, gary);
-            if (gary)
-                Safefree(gary);
+           Safefree(gary);
        }
 #else  /* HAS_SETGROUPS */
        PL_egid = SvIV(sv);
        }
 #else  /* HAS_SETGROUPS */
        PL_egid = SvIV(sv);
@@ -2570,15 +2611,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            setproctitle("%s", s);
 #   endif
        }
            setproctitle("%s", s);
 #   endif
        }
-#endif
-#if defined(__hpux) && defined(PSTAT_SETCMD)
+#elif defined(__hpux) && defined(PSTAT_SETCMD)
        if (PL_origalen != 1) {
             union pstun un;
             s = SvPV_const(sv, len);
             un.pst_command = (char *)s;
             pstat(PSTAT_SETCMD, un, len, 0, 0);
        }
        if (PL_origalen != 1) {
             union pstun un;
             s = SvPV_const(sv, len);
             un.pst_command = (char *)s;
             pstat(PSTAT_SETCMD, un, len, 0, 0);
        }
-#endif
+#else
        if (PL_origalen > 1) {
            /* PL_origalen is set in perl_parse(). */
            s = SvPV_force(sv,len);
        if (PL_origalen > 1) {
            /* PL_origalen is set in perl_parse(). */
            s = SvPV_force(sv,len);
@@ -2592,17 +2632,23 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                Copy(s, PL_origargv[0], len, char);
                PL_origargv[0][len] = 0;
                memset(PL_origargv[0] + len + 1,
                Copy(s, PL_origargv[0], len, char);
                PL_origargv[0][len] = 0;
                memset(PL_origargv[0] + len + 1,
+#ifdef PERL_DARWIN
+                      /* Special case for darwin: see [perl #38868] */
+                      (int)'\0',
+#else
                       /* Is the space counterintuitive?  Yes.
                       /* Is the space counterintuitive?  Yes.
-                       * (You were expecting \0?)  
+                       * (You were expecting \0?)
                        * Does it work?  Seems to.  (In Linux 2.4.20 at least.)
                        * --jhi */
                       (int)' ',
                        * Does it work?  Seems to.  (In Linux 2.4.20 at least.)
                        * --jhi */
                       (int)' ',
+#endif
                       PL_origalen - len - 1);
            }
            PL_origargv[0][PL_origalen-1] = 0;
            for (i = 1; i < PL_origargc; i++)
                PL_origargv[i] = 0;
        }
                       PL_origalen - len - 1);
            }
            PL_origargv[0][PL_origalen-1] = 0;
            for (i = 1; i < PL_origargc; i++)
                PL_origargv[i] = 0;
        }
+#endif
        UNLOCK_DOLLARZERO_MUTEX;
        break;
 #endif
        UNLOCK_DOLLARZERO_MUTEX;
        break;
 #endif
@@ -2732,7 +2778,7 @@ Perl_sighandler(int sig)
 #endif
                   EXTEND(SP, 2);
                   PUSHs((SV*)rv);
 #endif
                   EXTEND(SP, 2);
                   PUSHs((SV*)rv);
-                  PUSHs(newSVpv((void*)sip, sizeof(*sip)));
+                  PUSHs(newSVpv((char *)sip, sizeof(*sip)));
              }
 
               va_end(args);
              }
 
               va_end(args);
@@ -2807,10 +2853,10 @@ S_restore_magic(pTHX_ const void *p)
            /* downgrade public flags to private,
               and discard any other private flags */
 
            /* downgrade public flags to private,
               and discard any other private flags */
 
-           U32 public = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK);
-           if (public) {
-               SvFLAGS(sv) &= ~( public | SVp_IOK|SVp_NOK|SVp_POK );
-               SvFLAGS(sv) |= ( public << PRIVSHIFT );
+           const U32 pubflags = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK);
+           if (pubflags) {
+               SvFLAGS(sv) &= ~( pubflags | (SVp_IOK|SVp_NOK|SVp_POK) );
+               SvFLAGS(sv) |= ( pubflags << PRIVSHIFT );
            }
        }
     }
            }
        }
     }
@@ -2855,8 +2901,9 @@ S_unwind_handler_stack(pTHX_ const void *p)
 =for apidoc magic_sethint
 
 Triggered by a store to %^H, records the key/value pair to
 =for apidoc magic_sethint
 
 Triggered by a store to %^H, records the key/value pair to
-C<PL_compiling.cop_hints>.  It is assumed that hints aren't storing anything
-that would need a deep copy.  Maybe we should warn if we find a reference.
+C<PL_compiling.cop_hints_hash>.  It is assumed that hints aren't storing
+anything that would need a deep copy.  Maybe we should warn if we find a
+reference.
 
 =cut
 */
 
 =cut
 */
@@ -2875,8 +2922,8 @@ Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg)
        Doing this here saves a lot of doing it manually in perl code (and
        forgetting to do it, and consequent subtle errors.  */
     PL_hints |= HINT_LOCALIZE_HH;
        Doing this here saves a lot of doing it manually in perl code (and
        forgetting to do it, and consequent subtle errors.  */
     PL_hints |= HINT_LOCALIZE_HH;
-    PL_compiling.cop_hints
-       = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints,
+    PL_compiling.cop_hints_hash
+       = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
                                 (SV *)mg->mg_ptr, sv);
     return 0;
 }
                                 (SV *)mg->mg_ptr, sv);
     return 0;
 }
@@ -2884,7 +2931,8 @@ Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg)
 /*
 =for apidoc magic_sethint
 
 /*
 =for apidoc magic_sethint
 
-Triggered by a delete from %^H, records the key to C<PL_compiling.cop_hints>.
+Triggered by a delete from %^H, records the key to
+C<PL_compiling.cop_hints_hash>.
 
 =cut
 */
 
 =cut
 */
@@ -2892,13 +2940,15 @@ int
 Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
 Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
+    PERL_UNUSED_ARG(sv);
+
     assert(mg->mg_len == HEf_SVKEY);
 
     PERL_UNUSED_ARG(sv);
 
     PL_hints |= HINT_LOCALIZE_HH;
     assert(mg->mg_len == HEf_SVKEY);
 
     PERL_UNUSED_ARG(sv);
 
     PL_hints |= HINT_LOCALIZE_HH;
-    PL_compiling.cop_hints
-       = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints,
+    PL_compiling.cop_hints_hash
+       = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
                                 (SV *)mg->mg_ptr, &PL_sv_placeholder);
     return 0;
 }
                                 (SV *)mg->mg_ptr, &PL_sv_placeholder);
     return 0;
 }