This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
NI-S' cunning idea of how to de-UTF8 the "\C-broken" submatches.
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index a91d34b..931b1a1 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -412,10 +412,12 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
                    char *s    = rx->subbeg + s1;
                    char *send = rx->subbeg + t1;
 
-                   i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
+                   i = t1 - s1;
+                   if (is_utf8_string((U8*)s, i))
+                       i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
                }
                if (i < 0)
-                   Perl_croak(aTHX_ "panic: magic_len: %d", i);
+                   Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i);
                return i;
            }
        }
@@ -479,9 +481,9 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\004':               /* ^D */
-       sv_setiv(sv, (IV)(PL_debug & 32767));
+       sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK));
 #if defined(YYDEBUG) && defined(DEBUGGING)
-       PL_yydebug = (PL_debug & 1);
+       PL_yydebug = DEBUG_p_TEST;
 #endif
        break;
     case '\005':  /* ^E */
@@ -630,7 +632,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                        PL_tainted = FALSE;
                    }
                    sv_setpvn(sv, s, i);
-                   if (DO_UTF8(PL_reg_sv))
+                   if (DO_UTF8(PL_reg_sv) && is_utf8_string((U8*)s, i))
                        SvUTF8_on(sv);
                    else
                        SvUTF8_off(sv);
@@ -796,7 +798,7 @@ Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
 
     if (uf && uf->uf_val)
-       (*uf->uf_val)(uf->uf_index, sv);
+       (*uf->uf_val)(aTHX_ uf->uf_index, sv);
     return 0;
 }
 
@@ -996,6 +998,40 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
     return 0;
 }
 
+void
+Perl_raise_signal(pTHX_ int sig)
+{
+    /* Set a flag to say this signal is pending */
+    PL_psig_pend[sig]++;
+    /* And one to say _a_ signal is pending */
+    PL_sig_pending = 1;
+}
+
+Signal_t
+Perl_csighandler(int sig)
+{
+#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
+}
+
+void
+Perl_despatch_signals(pTHX)
+{
+    int sig;
+    PL_sig_pending = 0;
+    for (sig = 1; sig < SIG_SIZE; sig++) {
+       if (PL_psig_pend[sig]) {
+           PL_psig_pend[sig] = 0;
+           (*PL_sighandlerp)(sig);
+       }
+    }
+}
+
 int
 Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -1034,7 +1070,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     }
     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
        if (i)
-           (void)rsignal(i, PL_sighandlerp);
+           (void)rsignal(i, &Perl_csighandler);
        else
            *svp = SvREFCNT_inc(sv);
        return 0;
@@ -1061,7 +1097,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
        if (!strchr(s,':') && !strchr(s,'\''))
            sv_insert(sv, 0, 0, "main::", 6);
        if (i)
-           (void)rsignal(i, PL_sighandlerp);
+           (void)rsignal(i, &Perl_csighandler);
        else
            *svp = SvREFCNT_inc(sv);
     }
@@ -1404,12 +1440,14 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
     I32 offs = LvTARGOFF(sv);
     I32 rem = LvTARGLEN(sv);
 
+    if (SvUTF8(lsv))
+       sv_pos_u2b(lsv, &offs, &rem);
     if (offs > len)
        offs = len;
     if (rem + offs > len)
        rem = len - offs;
     sv_setpvn(sv, tmps + offs, (STRLEN)rem);
-    if (DO_UTF8(lsv))
+    if (SvUTF8(lsv))
         SvUTF8_on(sv);
     return 0;
 }
@@ -1417,25 +1455,26 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
 {
-    STRLEN littlelen;
-    char *tmps = SvPV(sv, littlelen);
+    STRLEN len;
+    char *tmps = SvPV(sv, len);
+    SV *lsv = LvTARG(sv);
+    I32 lvoff = LvTARGOFF(sv);
+    I32 lvlen = LvTARGLEN(sv);
 
     if (DO_UTF8(sv)) {
-       I32 bigoff = LvTARGOFF(sv);
-       I32 biglen = LvTARGLEN(sv);
-       U8 *s, *a, *b;
-
-       sv_utf8_upgrade(LvTARG(sv));
-       /* sv_utf8_upgrade() might have moved and/or resized
-        * the string to be replaced, we must rediscover it. --jhi */
-       s = (U8*)SvPVX(LvTARG(sv));
-       a = utf8_hop(s, bigoff);
-       b = utf8_hop(a, biglen);
-       sv_insert(LvTARG(sv), a - s, b - a, tmps, littlelen);
-       SvUTF8_on(LvTARG(sv));
+       sv_utf8_upgrade(lsv);
+       sv_pos_u2b(lsv, &lvoff, &lvlen);
+       sv_insert(lsv, lvoff, lvlen, tmps, len);
+       SvUTF8_on(lsv);
+    }
+    else if (SvUTF8(lsv)) {
+       sv_pos_u2b(lsv, &lvoff, &lvlen);
+       tmps = (char*)bytes_to_utf8((U8*)tmps, &len);
+       sv_insert(lsv, lvoff, lvlen, tmps, len);
+       Safefree(tmps);
     }
     else
-        sv_insert(LvTARG(sv), LvTARGOFF(sv), LvTARGLEN(sv), tmps, littlelen);
+        sv_insert(lsv, lvoff, lvlen, tmps, len);
 
     return 0;
 }
@@ -1630,7 +1669,7 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
 
     if (uf && uf->uf_set)
-       (*uf->uf_set)(uf->uf_index, sv);
+       (*uf->uf_set)(aTHX_ uf->uf_index, sv);
     return 0;
 }
 
@@ -1674,7 +1713,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\004':       /* ^D */
-       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
+       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
        DEBUG_x(dump_all());
        break;
     case '\005':  /* ^E */
@@ -2227,6 +2266,7 @@ Perl_sighandler(int sig)
 
     POPSTACK;
     if (SvTRUE(ERRSV)) {
+#ifndef PERL_MICRO
 #ifdef HAS_SIGPROCMASK
        /* Handler "died", for example to get out of a restart-able read().
         * Before we re-do that on its behalf re-enable the signal which was
@@ -2239,8 +2279,9 @@ Perl_sighandler(int sig)
 #else
        /* Not clear if this will work */
        (void)rsignal(sig, SIG_IGN);
-       (void)rsignal(sig, PL_sighandlerp);
+       (void)rsignal(sig, &Perl_csighandler);
 #endif
+#endif /* !PERL_MICRO */
        Perl_die(aTHX_ Nullch);
     }
 cleanup: