This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Plan 9: No Configure.
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index 9fe3369..fae5cda 100644 (file)
--- a/mg.c
+++ b/mg.c
 #  endif
 #endif
 
+#ifdef __hpux
+#  include <sys/pstat.h>
+#endif
+
 /* if you only have signal() and it resets on each signal, FAKE_PERSISTENT_SIGNAL_HANDLERS fixes */
 #if !defined(HAS_SIGACTION) && defined(VMS)
 #  define  FAKE_PERSISTENT_SIGNAL_HANDLERS
@@ -57,6 +61,11 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
 {
     MGS* mgs;
     assert(SvMAGICAL(sv));
+#ifdef PERL_COPY_ON_WRITE
+    /* Turning READONLY off for a copy-on-write scalar is a bad idea.  */
+    if (SvIsCOW(sv))
+      sv_force_normal(sv);
+#endif
 
     SAVEDESTRUCTOR_X(restore_magic, INT2PTR(void*, (IV)mgs_ix));
 
@@ -400,7 +409,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
        paren = mg->mg_len;
        if (paren < 0)
            return 0;
-       if (paren <= rx->nparens &&
+       if (paren <= (I32)rx->nparens &&
            (s = rx->startp[paren]) != -1 &&
            (t = rx->endp[paren]) != -1)
            {
@@ -444,7 +453,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
 
            paren = atoi(mg->mg_ptr); /* $& is in [0] */
          getparen:
-           if (paren <= rx->nparens &&
+           if (paren <= (I32)rx->nparens &&
                (s1 = rx->startp[paren]) != -1 &&
                (t1 = rx->endp[paren]) != -1)
            {
@@ -454,6 +463,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
                    char *s    = rx->subbeg + s1;
                    char *send = rx->subbeg + t1;
 
+                    i = t1 - s1;
                    if (is_utf8_string((U8*)s, i))
                        i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
                }
@@ -648,9 +658,15 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 #endif
         }
         else if (strEQ(mg->mg_ptr, "\024AINT"))
-            sv_setiv(sv, PL_tainting);
+            sv_setiv(sv, PL_tainting
+                   ? (PL_taint_warn || PL_unsafe ? -1 : 1)
+                   : 0);
+        break;
+    case '\025':               /* $^UTF8_LOCALE */
+        if (strEQ(mg->mg_ptr, "\025TF8_LOCALE"))
+           sv_setiv(sv, (IV) (PL_wantutf8 && PL_utf8locale));
         break;
-    case '\027':               /* ^W  & $^WARNING_BITS & ^WIDE_SYSTEM_CALLS */
+    case '\027':               /* ^W  & $^WARNING_BITS */
        if (*(mg->mg_ptr+1) == '\0')
            sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) ? TRUE : FALSE));
        else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
@@ -667,8 +683,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
            }
            SvPOK_only(sv);
        }
-       else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS"))
-           sv_setiv(sv, (IV)PL_widesyscalls);
        break;
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
@@ -681,7 +695,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
             */
            paren = atoi(mg->mg_ptr); /* $& is in [0] */
          getparen:
-           if (paren <= rx->nparens &&
+           if (paren <= (I32)rx->nparens &&
                (s1 = rx->startp[paren]) != -1 &&
                (t1 = rx->endp[paren]) != -1)
            {
@@ -692,18 +706,25 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 
              getrx:
                if (i >= 0) {
-                   bool was_tainted = FALSE;
-                   if (PL_tainting) {
-                       was_tainted = PL_tainted;
-                       PL_tainted = FALSE;
-                   }
                    sv_setpvn(sv, s, i);
-                   if (PL_reg_match_utf8 && is_utf8_string((U8*)s, i))
+                   if (PL_reg_match_utf8 && is_utf8_string((U8*)s, i))
                        SvUTF8_on(sv);
                    else
                        SvUTF8_off(sv);
-                   if (PL_tainting)
-                       PL_tainted = (was_tainted || RX_MATCH_TAINTED(rx));
+                   if (PL_tainting) {
+                       if (RX_MATCH_TAINTED(rx)) {
+                           MAGIC* mg = SvMAGIC(sv);
+                           MAGIC* mgt;
+                           PL_tainted = 1;
+                           SvMAGIC(sv) = mg->mg_moremagic;
+                           SvTAINT(sv);
+                           if ((mgt = SvMAGIC(sv))) {
+                               mg->mg_moremagic = mgt;
+                               SvMAGIC(sv) = mg;
+                           }
+                       } else
+                           SvTAINTED_off(sv);
+                   }
                    break;
                }
            }
@@ -801,7 +822,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        break;
     case '\\':
        if (PL_ors_sv)
-           sv_setpv(sv,SvPVX(PL_ors_sv));
+           sv_copypv(sv, PL_ors_sv);
        break;
     case '#':
        sv_setpv(sv,PL_ofmt);
@@ -859,11 +880,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '0':
        break;
 #endif
-#ifdef USE_5005THREADS
-    case '@':
-       sv_setsv(sv, thr->errsv);
-       break;
-#endif /* USE_5005THREADS */
     }
     return 0;
 }
@@ -907,7 +923,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
 #ifdef VMS
        if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
            char pathbuf[256], eltbuf[256], *cp, *elt = s;
-           struct stat sbuf;
+           Stat_t sbuf;
            int i = 0, j = 0;
 
            do {          /* DCL$PATH may be a search list */
@@ -935,7 +951,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
 
            while (s < strend) {
                char tmpbuf[256];
-               struct stat st;
+               Stat_t st;
                I32 i;
                s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
                             s, strend, ':', &i);
@@ -989,11 +1005,16 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 #if defined(VMS) || defined(EPOC)
     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
 #else
-#   if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
+#  if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
     PerlEnv_clearenv();
-#   else
-#       ifdef USE_ENVIRON_ARRAY
-#          ifndef PERL_USE_SAFE_PUTENV
+#  else
+#    ifdef USE_ENVIRON_ARRAY
+#      if defined(USE_ITHREADS)
+    /* only the parent thread can clobber the process environment */
+    if (PL_curinterp == aTHX)
+#      endif
+    {
+#      ifndef PERL_USE_SAFE_PUTENV
     I32 i;
 
     if (environ == PL_origenviron)
@@ -1001,11 +1022,11 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
     else
        for (i = 0; environ[i]; i++)
            safesysfree(environ[i]);
-#          endif /* PERL_USE_SAFE_PUTENV */
+#      endif /* PERL_USE_SAFE_PUTENV */
 
     environ[0] = Nullch;
-
-#       endif /* USE_ENVIRON_ARRAY */
+    }
+#    endif /* USE_ENVIRON_ARRAY */
 #   endif /* PERL_IMPLICIT_SYS || WIN32 */
 #endif /* VMS || EPC */
     return 0;
@@ -1437,8 +1458,13 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
     i = SvTRUE(sv);
     svp = av_fetch(GvAV(gv),
                     atoi(MgPV(mg,n_a)), FALSE);
-    if (svp && SvIOKp(*svp) && (o = INT2PTR(OP*,SvIVX(*svp))))
-       o->op_private = i;
+    if (svp && SvIOKp(*svp) && (o = INT2PTR(OP*,SvIVX(*svp)))) {
+       /* set or clear breakpoint in the relevant control op */
+       if (i)
+           o->op_flags |= OPf_SPECIAL;
+       else
+           o->op_flags &= ~OPf_SPECIAL;
+    }
     return 0;
 }
 
@@ -1512,7 +1538,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
        if (pos < 0)
            pos = 0;
     }
-    else if (pos > len)
+    else if (pos > (SSize_t)len)
        pos = len;
 
     if (ulen) {
@@ -1572,9 +1598,9 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
 
     if (SvUTF8(lsv))
        sv_pos_u2b(lsv, &offs, &rem);
-    if (offs > len)
+    if (offs > (I32)len)
        offs = len;
-    if (rem + offs > len)
+    if (rem + offs > (I32)len)
        rem = len - offs;
     sv_setpvn(sv, tmps + offs, (STRLEN)rem);
     if (SvUTF8(lsv))
@@ -1661,16 +1687,9 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
     if (LvTARGLEN(sv)) {
        if (mg->mg_obj) {
            SV *ahv = LvTARG(sv);
-           if (SvTYPE(ahv) == SVt_PVHV) {
-               HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
-               if (he)
-                   targ = HeVAL(he);
-           }
-           else {
-               SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0);
-               if (svp)
-                   targ = *svp;
-           }
+            HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
+            if (he)
+                targ = HeVAL(he);
        }
        else {
            AV* av = (AV*)LvTARG(sv);
@@ -1716,16 +1735,9 @@ Perl_vivify_defelem(pTHX_ SV *sv)
     if (mg->mg_obj) {
        SV *ahv = LvTARG(sv);
        STRLEN n_a;
-       if (SvTYPE(ahv) == SVt_PVHV) {
-           HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
-           if (he)
-               value = HeVAL(he);
-       }
-       else {
-           SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0);
-           if (svp)
-               value = *svp;
-       }
+        HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
+        if (he)
+            value = HeVAL(he);
        if (!value || value == &PL_sv_undef)
            Perl_croak(aTHX_ PL_no_helem, SvPV(mg->mg_obj, n_a));
     }
@@ -1828,6 +1840,16 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
 }
 #endif /* USE_LOCALE_COLLATE */
 
+/* Just clear the UTF-8 cache data. */
+int
+Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg)
+{
+    Safefree(mg->mg_ptr);      /* The mg_ptr holds the pos cache. */
+    mg->mg_ptr = 0;
+    mg->mg_len = -1;           /* The mg_len holds the len cache. */
+    return 0;
+}
+
 int
 Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -1839,7 +1861,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        sv_setsv(PL_bodytarget, sv);
        break;
     case '\003':       /* ^C */
-       PL_minus_c = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+       PL_minus_c = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
 
     case '\004':       /* ^D */
@@ -1847,32 +1869,37 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        DEBUG_x(dump_all());
        break;
     case '\005':  /* ^E */
-        if (*(mg->mg_ptr+1) == '\0') {
+       if (*(mg->mg_ptr+1) == '\0') {
 #ifdef MACOS_TRADITIONAL
-             gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+           gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
 #else
 #  ifdef VMS
-             set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+           set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
 #  else
 #    ifdef WIN32
-             SetLastError( SvIV(sv) );
+           SetLastError( SvIV(sv) );
 #    else
 #      ifdef OS2
-             os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+           os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
 #      else
-             /* will anyone ever use this? */
-             SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
+           /* will anyone ever use this? */
+           SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
 #      endif
 #    endif
 #  endif
 #endif
-        }
-        else if (strEQ(mg->mg_ptr+1, "NCODING")) {
-            if (PL_encoding)
-                sv_setsv(PL_encoding, sv);
-            else
-                PL_encoding = newSVsv(sv);
-        }
+       }
+       else if (strEQ(mg->mg_ptr+1, "NCODING")) {
+           if (PL_encoding)
+               SvREFCNT_dec(PL_encoding);
+           if (SvOK(sv) || SvGMAGICAL(sv)) {
+               PL_encoding = newSVsv(sv);
+           }
+           else {
+               PL_encoding = Nullsv;
+           }
+       }
+       break;
     case '\006':       /* ^F */
        PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
        break;
@@ -1915,7 +1942,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
 #endif
        break;
-    case '\027':       /* ^W & $^WARNING_BITS & ^WIDE_SYSTEM_CALLS */
+    case '\025':       /* $^UTF8_LOCALE */
+        if (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv))
+           PL_wantutf8 = PL_utf8locale;
+       else
+           PL_wantutf8 = FALSE;
+        break;
+    case '\027':       /* ^W & $^WARNING_BITS */
        if (*(mg->mg_ptr+1) == '\0') {
            if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
                i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
@@ -1957,8 +1990,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                }
            }
        }
-       else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS"))
-           PL_widesyscalls = SvTRUE(sv);
        break;
     case '.':
        if (PL_localizing) {
@@ -2058,8 +2089,15 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '!':
+        {
+#ifdef VMS
+#   define PERL_VMS_BANG vaxc$errno
+#else
+#   define PERL_VMS_BANG 0
+#endif
        SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0,
-                (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
+                (SvIV(sv) == EVMSERR) ? 4 : PERL_VMS_BANG);
+       }
        break;
     case '<':
        PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
@@ -2196,6 +2234,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        break;
 #ifndef MACOS_TRADITIONAL
     case '0':
+       LOCK_DOLLARZERO_MUTEX;
 #ifdef HAS_SETPROCTITLE
        /* The BSDs don't show the argv[] in ps(1) output, they
         * show a string from the process struct and provide
@@ -2220,6 +2259,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #   endif
        }
 #endif
+#if defined(__hpux) && defined(PSTAT_SETCMD)
+       {
+            union pstun un;
+            s = SvPV(sv, len);
+            un.pst_command = s;
+            pstat(PSTAT_SETCMD, un, len, 0, 0);
+       }
+#endif
        if (!PL_origalen) {
            s = PL_origargv[0];
            s += strlen(s);
@@ -2238,7 +2285,12 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                    break;
            }
            /* can grab env area too? */
-           if (PL_origenviron && (PL_origenviron[0] == s + 1)) {
+           if (PL_origenviron
+#ifdef USE_ITHREADS
+               && PL_curinterp == aTHX
+#endif
+               && (PL_origenviron[0] == s + 1))
+           {
                my_setenv("NoNe  SuCh", Nullch);
                                            /* force copy of environment */
                for (i = 0; PL_origenviron[i]; i++)
@@ -2253,7 +2305,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        }
        s = SvPV_force(sv,len);
        i = len;
-       if (i >= PL_origalen) {
+       if (i >= (I32)PL_origalen) {
            i = PL_origalen;
            /* don't allow system to limit $0 seen by script */
            /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
@@ -2265,38 +2317,18 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            Copy(s, PL_origargv[0], i, char);
            s = PL_origargv[0]+i;
            *s++ = '\0';
-           while (++i < PL_origalen)
-               *s++ = ' ';
-           s = PL_origargv[0]+i;
+           while (++i < (I32)PL_origalen)
+               *s++ = '\0';
            for (i = 1; i < PL_origargc; i++)
                PL_origargv[i] = Nullch;
        }
+       UNLOCK_DOLLARZERO_MUTEX;
        break;
 #endif
-#ifdef USE_5005THREADS
-    case '@':
-       sv_setsv(thr->errsv, sv);
-       break;
-#endif /* USE_5005THREADS */
     }
     return 0;
 }
 
-#ifdef USE_5005THREADS
-int
-Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg)
-{
-    DEBUG_S(PerlIO_printf(Perl_debug_log,
-                         "0x%"UVxf": magic_mutexfree 0x%"UVxf"\n",
-                         PTR2UV(thr), PTR2UV(sv)));
-    if (MgOWNER(mg))
-       Perl_croak(aTHX_ "panic: magic_mutexfree");
-    MUTEX_DESTROY(MgMUTEXP(mg));
-    COND_DESTROY(MgCONDP(mg));
-    return 0;
-}
-#endif /* USE_5005THREADS */
-
 I32
 Perl_whichsig(pTHX_ char *sig)
 {