This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
NetWare tweak from Ananth Kesari.
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index 3608e6a..30f91ee 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -1,6 +1,6 @@
 /*    mg.c
  *
- *    Copyright (c) 1991-2001, Larry Wall
+ *    Copyright (c) 1991-2002, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
  * come here, and I don't want to see no more magic,' he said, and fell silent."
  */
 
+/*
+=head1 Magical Functions
+*/
+
 #include "EXTERN.h"
 #define PERL_IN_MG_C
 #include "perl.h"
 #  endif
 #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
+#endif
+/* if we're doing kill() with sys$sigprc on VMS, FAKE_DEFAULT_SIGNAL_HANDLERS */
+#if defined(KILL_BY_SIGPRC)
+#  define  FAKE_DEFAULT_SIGNAL_HANDLERS
+#endif
+
 static void restore_magic(pTHX_ void *p);
 static void unwind_handler_stack(pTHX_ void *p);
 
@@ -199,7 +212,7 @@ Perl_mg_length(pTHX_ SV *sv)
        }
     }
 
-    if (DO_UTF8(sv)) 
+    if (DO_UTF8(sv))
     {
         U8 *s = (U8*)SvPV(sv, len);
         len = Perl_utf8_length(aTHX_ s, s + len);
@@ -262,7 +275,7 @@ Perl_mg_clear(pTHX_ SV *sv)
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
        MGVTBL* vtbl = mg->mg_virtual;
        /* omit GSKIP -- never set here */
-       
+
        if (vtbl && vtbl->svt_clear)
            CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg);
     }
@@ -306,7 +319,11 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
     int count = 0;
     MAGIC* mg;
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       if (isUPPER(mg->mg_type)) {
+       MGVTBL* vtbl = mg->mg_virtual;
+       if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){
+           count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen);
+       }
+       else if (isUPPER(mg->mg_type)) {
            sv_magic(nsv,
                     mg->mg_type == PERL_MAGIC_tied ? SvTIED_obj(sv, mg) :
                     (mg->mg_type == PERL_MAGIC_regdata && mg->mg_obj)
@@ -337,7 +354,7 @@ Perl_mg_free(pTHX_ SV *sv)
        if (vtbl && vtbl->svt_free)
            CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
        if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
-           if (mg->mg_len >= 0)
+           if (mg->mg_len > 0)
                Safefree(mg->mg_ptr);
            else if (mg->mg_len == HEf_SVKEY)
                SvREFCNT_dec((SV*)mg->mg_ptr);
@@ -391,7 +408,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
                    i = t;
                else                    /* @- */
                    i = s;
-               
+
                if (i > 0 && PL_reg_match_utf8) {
                    char *b = rx->subbeg;
                    if (b)
@@ -445,6 +462,14 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
                    Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i);
                return i;
            }
+           else {
+               if (ckWARN(WARN_UNINITIALIZED))
+                   report_uninit();
+           }
+       }
+       else {
+           if (ckWARN(WARN_UNINITIALIZED))
+               report_uninit();
        }
        return 0;
     case '+':
@@ -523,11 +548,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 #ifdef MACOS_TRADITIONAL
             {
                  char msg[256];
-       
+
                  sv_setnv(sv,(double)gMacPerl_OSErr);
-                 sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : "");       
+                 sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : "");
             }
-#else  
+#else
 #ifdef VMS
             {
 #                include <descrip.h>
@@ -776,6 +801,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case ',':
        break;
     case '\\':
+       if (PL_ors_sv)
+           sv_setpv(sv,SvPVX(PL_ors_sv));
        break;
     case '#':
        sv_setpv(sv,PL_ofmt);
@@ -858,7 +885,6 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
     register char *s;
     char *ptr;
     STRLEN len, klen;
-    I32 i;
 
     s = SvPV(sv,len);
     ptr = MgPV(mg,klen);
@@ -911,6 +937,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
            while (s < strend) {
                char tmpbuf[256];
                struct stat st;
+               I32 i;
                s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
                             s, strend, ':', &i);
                s++;
@@ -985,6 +1012,16 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
     return 0;
 }
 
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS)||defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+static int sig_handlers_initted = 0;
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+static int sig_ignoring[SIG_SIZE];      /* which signals we are ignoring */
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+static int sig_defaulting[SIG_SIZE];
+#endif
+
 #ifndef PERL_MICRO
 int
 Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
@@ -997,8 +1034,14 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
        if(PL_psig_ptr[i])
            sv_setsv(sv,PL_psig_ptr[i]);
        else {
-           Sighandler_t sigstate = rsignal_state(i);
-
+           Sighandler_t sigstate;
+           sigstate = rsignal_state(i);
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+           if (sig_handlers_initted && sig_ignoring[i]) sigstate = SIG_IGN;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+           if (sig_handlers_initted && sig_defaulting[i]) sigstate = SIG_DFL;
+#endif
            /* cache state so we don't fetch it again */
            if(sigstate == SIG_IGN)
                sv_setpv(sv,"IGNORE");
@@ -1042,15 +1085,53 @@ Perl_raise_signal(pTHX_ int sig)
 Signal_t
 Perl_csighandler(int sig)
 {
+#ifdef PERL_GET_SIG_CONTEXT
+    dTHXa(PERL_GET_SIG_CONTEXT);
+#else
+    dTHX;
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+    (void) rsignal(sig, &Perl_csighandler);
+    if (sig_ignoring[sig]) return;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+    if (sig_defaulting[sig])
+#ifdef KILL_BY_SIGPRC
+            exit((Perl_sig_to_vmscondition(sig)&STS$M_COND_ID)|STS$K_SEVERE|STS$M_INHIB_MSG);
+#else
+            exit(1);
+#endif
+#endif
+
 #ifdef PERL_OLD_SIGNALS
     /* Call the perl level handler now with risk we may be in malloc() etc. */
     (*PL_sighandlerp)(sig);
 #else
-    dTHX;
     Perl_raise_signal(aTHX_ sig);
 #endif
 }
 
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+void
+Perl_csighandler_init(void)
+{
+    int sig;
+    if (sig_handlers_initted) return;
+
+    for (sig = 1; sig < SIG_SIZE; sig++) {
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+        dTHX;
+        sig_defaulting[sig] = 1;
+        (void) rsignal(sig, &Perl_csighandler);
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+        sig_ignoring[sig] = 0;
+#endif
+    }
+    sig_handlers_initted = 1;
+}
+#endif
+
 void
 Perl_despatch_signals(pTHX)
 {
@@ -1093,6 +1174,15 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
                Perl_warner(aTHX_ WARN_SIGNAL, "No such signal: SIG%s", s);
            return 0;
        }
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+       if (!sig_handlers_initted) Perl_csighandler_init();
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+       sig_ignoring[i] = 0;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+         sig_defaulting[i] = 0;
+#endif
        SvREFCNT_dec(PL_psig_name[i]);
        SvREFCNT_dec(PL_psig_ptr[i]);
        PL_psig_ptr[i] = SvREFCNT_inc(sv);
@@ -1109,14 +1199,26 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     }
     s = SvPV_force(sv,len);
     if (strEQ(s,"IGNORE")) {
-       if (i)
+       if (i) {
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+           sig_ignoring[i] = 1;
+           (void)rsignal(i, &Perl_csighandler);
+#else
            (void)rsignal(i, SIG_IGN);
-       else
+#endif
+       } else
            *svp = 0;
     }
     else if (strEQ(s,"DEFAULT") || !*s) {
        if (i)
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+         {
+           sig_defaulting[i] = 1;
+           (void)rsignal(i, &Perl_csighandler);
+         }
+#else
            (void)rsignal(i, SIG_DFL);
+#endif
        else
            *svp = 0;
     }
@@ -1158,7 +1260,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
 {
     HV *hv = (HV*)LvTARG(sv);
     I32 i = 0;
-     
+
     if (hv) {
          (void) hv_iterinit(hv);
          if (! SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
@@ -1419,7 +1521,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
        sv_pos_u2b(lsv, &p, 0);
        pos = p;
     }
-       
+
     mg->mg_len = pos;
     mg->mg_flags &= ~MGf_MINMATCH;
 
@@ -1843,7 +1945,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                    else if (isWARN_on(sv, WARN_ALL) && !any_fatals) {
                        PL_compiling.cop_warnings = pWARN_ALL;
                        PL_dowarn |= G_WARN_ONCE ;
-                   }   
+                   }
                     else {
                        if (specialWARN(PL_compiling.cop_warnings))
                            PL_compiling.cop_warnings = newSVsv(sv) ;
@@ -1865,7 +1967,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                SAVESPTR(PL_last_in_gv);
        }
        else if (SvOK(sv) && GvIO(PL_last_in_gv))
-           IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
+           IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv);
        break;
     case '^':
        Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
@@ -1878,15 +1980,15 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
        break;
     case '=':
-       IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '-':
-       IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
            IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
        break;
     case '%':
-       IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoPAGE(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '|':
        {
@@ -2222,8 +2324,8 @@ static SV* sig_sv;
 Signal_t
 Perl_sighandler(int sig)
 {
-#if defined(WIN32) && defined(PERL_IMPLICIT_CONTEXT)
-    dTHXa(PL_curinterp);       /* fake TLS, because signals don't do TLS */
+#ifdef PERL_GET_SIG_CONTEXT
+    dTHXa(PERL_GET_SIG_CONTEXT);
 #else
     dTHX;
 #endif
@@ -2236,10 +2338,6 @@ Perl_sighandler(int sig)
     U32 flags = 0;
     XPV *tXpv = PL_Xpv;
 
-#if defined(WIN32) && defined(PERL_IMPLICIT_CONTEXT)
-    PERL_SET_THX(aTHX);        /* fake TLS, see above */
-#endif
-
     if (PL_savestack_ix + 15 <= PL_savestack_max)
        flags |= 1;
     if (PL_markstack_ptr < PL_markstack_max - 2)
@@ -2249,9 +2347,11 @@ Perl_sighandler(int sig)
     if (PL_scopestack_ix < PL_scopestack_max - 3)
        flags |= 16;
 
-    if (!PL_psig_ptr[sig])
-       Perl_die(aTHX_ "Signal SIG%s received, but no signal handler set.\n",
-           PL_sig_name[sig]);
+    if (!PL_psig_ptr[sig]) {
+               Perl_warn(aTHX_ "Signal SIG%s received, but no signal handler set.\n",
+                                PL_sig_name[sig]);
+               exit(sig);
+       }
 
     /* Max number of items pushed there is 3*n or 4. We cannot fix
        infinity, so we fix 4 (in fact 5): */
@@ -2393,3 +2493,5 @@ unwind_handler_stack(pTHX_ void *p)
        SvREFCNT_dec(sig_sv);
 #endif
 }
+
+