This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
for pod/perlfaq2.pod against latest snapshot for Alpaca
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index 433cc23..b69da05 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -1,6 +1,7 @@
 /*    mg.c
  *
- *    Copyright (c) 1991-2003, Larry Wall
+ *    Copyright (C) 1991, 1992, 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.
@@ -33,6 +34,8 @@
 #  include <sys/pstat.h>
 #endif
 
+Signal_t Perl_csighandler(int sig);
+
 /* 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
@@ -131,6 +134,12 @@ Perl_mg_get(pTHX_ SV *sv)
 
        if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
            CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
+
+           /* guard against sv having been freed */
+           if (SvTYPE(sv) == SVTYPEMASK) {
+               Perl_croak(aTHX_ "Tied variable freed while still in use");
+           }
+
            /* Don't restore the flags for this entry if it was deleted. */
            if (mg->mg_flags & MGf_GSKIP)
                (SSPTR(mgs_ix, MGS *))->mgs_flags = 0;
@@ -676,7 +685,16 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                sv_setpvn(sv, WARN_NONEstring, WARNsize) ;
             }
             else if (PL_compiling.cop_warnings == pWARN_ALL) {
-               sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
+               /* Get the bit mask for $warnings::Bits{all}, because
+                * it could have been extended by warnings::register */
+               SV **bits_all;
+               HV *bits=get_hv("warnings::Bits", FALSE);
+               if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) {
+                   sv_setsv(sv, *bits_all);
+               }
+               else {
+                   sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
+               }
            }
             else {
                sv_setsv(sv, PL_compiling.cop_warnings);
@@ -874,8 +892,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 #endif
        (void)SvIOK_on(sv);     /* what a wonderful hack! */
        break;
-    case '*':
-       break;
 #ifndef MACOS_TRADITIONAL
     case '0':
        break;
@@ -1058,7 +1074,7 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
     STRLEN n_a;
     /* Are we fetching a signal entry? */
     i = whichsig(MgPV(mg,n_a));
-    if (i) {
+    if (i > 0) {
        if(PL_psig_ptr[i])
            sv_setsv(sv,PL_psig_ptr[i]);
        else {
@@ -1109,7 +1125,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
        I32 i;
        /* Are we clearing a signal entry? */
        i = whichsig(s);
-       if (i) {
+       if (i > 0) {
 #ifdef HAS_SIGPROCMASK
            sigset_t set, save;
            SV* save_sv;
@@ -1256,7 +1272,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     }
     else {
        i = whichsig(s);        /* ...no, a brick */
-       if (!i) {
+       if (i < 0) {
            if (ckWARN(WARN_SIGNAL))
                Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
            return 0;
@@ -1865,6 +1881,7 @@ Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
        }
        i--;
     }
+    SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */
     return 0;
 }
 
@@ -1959,8 +1976,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\004':       /* ^D */
-       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
+#ifdef DEBUGGING
+       s = SvPV_nolen(sv);
+       PL_debug = get_debug_opts(&s) | DEBUG_TOP_FLAG;
        DEBUG_x(dump_all());
+#else
+       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
+#endif
        break;
     case '\005':  /* ^E */
        if (*(mg->mg_ptr+1) == '\0') {
@@ -2125,10 +2147,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            }
        }
        break;
-    case '*':
-       i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
-       PL_multiline = (i != 0);
-       break;
     case '/':
        SvREFCNT_dec(PL_rs);
        PL_rs = newSVsv(sv);
@@ -2355,60 +2373,26 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
             pstat(PSTAT_SETCMD, un, len, 0, 0);
        }
 #endif
-       if (!PL_origalen) {
-           s = PL_origargv[0];
-           s += strlen(s);
-           /* See if all the arguments are contiguous in memory */
-           for (i = 1; i < PL_origargc; i++) {
-               if (PL_origargv[i] == s + 1
-#ifdef OS2
-                   || PL_origargv[i] == s + 2
-#endif
-                  )
-               {
-                   ++s;
-                   s += strlen(s);     /* this one is ok too */
-               }
-               else
-                   break;
-           }
-           /* can grab env area too? */
-           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++)
-                   if (PL_origenviron[i] == s + 1) {
-                       ++s;
-                       s += strlen(s);
-                   }
-                   else
-                       break;
-           }
-           PL_origalen = s - PL_origargv[0];
-       }
+       /* PL_origalen is set in perl_parse(). */
        s = SvPV_force(sv,len);
-       i = len;
-       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'; */
-           Copy(s, PL_origargv[0], i, char);
-           s = PL_origargv[0]+i;
-           *s = '\0';
+       if (len >= (I32)PL_origalen) {
+           /* Longer than original, will be truncated. */
+           Copy(s, PL_origargv[0], PL_origalen, char);
+           PL_origargv[0][PL_origalen - 1] = 0;
        }
        else {
-           Copy(s, PL_origargv[0], i, char);
-           s = PL_origargv[0]+i;
-           *s++ = '\0';
-           while (++i < (I32)PL_origalen)
-               *s++ = '\0';
+           /* Shorter than original, will be padded. */
+           Copy(s, PL_origargv[0], len, char);
+           PL_origargv[0][len] = 0;
+           memset(PL_origargv[0] + len + 1,
+                  /* Is the space counterintuitive?  Yes.
+                   * (You were expecting \0?)  
+                   * Does it work?  Seems to.  (In Linux 2.4.20 at least.)
+                   * --jhi */
+                  (int)' ',
+                  PL_origalen - len - 1);
            for (i = 1; i < PL_origargc; i++)
-               PL_origargv[i] = Nullch;
+                PL_origargv[i] = 0;
        }
        UNLOCK_DOLLARZERO_MUTEX;
        break;
@@ -2422,7 +2406,7 @@ Perl_whichsig(pTHX_ char *sig)
 {
     register char **sigv;
 
-    for (sigv = PL_sig_name+1; *sigv; sigv++)
+    for (sigv = PL_sig_name; *sigv; sigv++)
        if (strEQ(sig,*sigv))
            return PL_sig_num[sigv - PL_sig_name];
 #ifdef SIGCLD
@@ -2433,7 +2417,7 @@ Perl_whichsig(pTHX_ char *sig)
     if (strEQ(sig,"CLD"))
        return SIGCHLD;
 #endif
-    return 0;
+    return -1;
 }
 
 #if !defined(PERL_IMPLICIT_CONTEXT)