This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[DOC PATCH] Adding new warning in perldiag.pod
[perl5.git] / regexec.c
index a7b6411..4a19958 100644 (file)
--- a/regexec.c
+++ b/regexec.c
  */
 
 #define CHR_SVLEN(sv) (UTF ? sv_len_utf8(sv) : SvCUR(sv))
-#define CHR_DIST(a,b) (DO_UTF8(PL_reg_sv) ? utf8_distance(a,b) : a - b)
+#define CHR_DIST(a,b) (PL_reg_sv_utf8 ? utf8_distance(a,b) : a - b)
 
 #define reghop_c(pos,off) ((char*)reghop((U8*)pos, off))
 #define reghopmaybe_c(pos,off) ((char*)reghopmaybe((U8*)pos, off))
-#define HOP(pos,off) (DO_UTF8(PL_reg_sv) ? reghop((U8*)pos, off) : (U8*)(pos + off))
-#define HOPMAYBE(pos,off) (DO_UTF8(PL_reg_sv) ? reghopmaybe((U8*)pos, off) : (U8*)(pos + off))
+#define HOP(pos,off) (PL_reg_sv_utf8 ? reghop((U8*)pos, off) : (U8*)(pos + off))
+#define HOPMAYBE(pos,off) (PL_reg_sv_utf8 ? reghopmaybe((U8*)pos, off) : (U8*)(pos + off))
 #define HOPc(pos,off) ((char*)HOP(pos,off))
 #define HOPMAYBEc(pos,off) ((char*)HOPMAYBE(pos,off))
 
+#define HOPBACK(pos, off) (            \
+    (UTF && PL_reg_sv_utf8)            \
+       ? reghopmaybe((U8*)pos, -off)   \
+    : (pos - off >= PL_bostr)          \
+       ? (U8*)(pos - off)              \
+    : (U8*)NULL                                \
+)
+#define HOPBACKc(pos, off) (char*)HOPBACK(pos, off)
+
 #define reghop3_c(pos,off,lim) ((char*)reghop3((U8*)pos, off, (U8*)lim))
 #define reghopmaybe3_c(pos,off,lim) ((char*)reghopmaybe3((U8*)pos, off, (U8*)lim))
-#define HOP3(pos,off,lim) (DO_UTF8(PL_reg_sv) ? reghop3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off))
-#define HOPMAYBE3(pos,off,lim) (DO_UTF8(PL_reg_sv) ? reghopmaybe3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off))
+#define HOP3(pos,off,lim) (PL_reg_sv_utf8 ? reghop3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off))
+#define HOPMAYBE3(pos,off,lim) (PL_reg_sv_utf8 ? reghopmaybe3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off))
 #define HOP3c(pos,off,lim) ((char*)HOP3(pos,off,lim))
 #define HOPMAYBE3c(pos,off,lim) ((char*)HOPMAYBE3(pos,off,lim))
 
@@ -135,7 +144,10 @@ S_regcppush(pTHX_ I32 parenfloor)
     int paren_elems_to_push = (PL_regsize - parenfloor) * REGCP_PAREN_ELEMS;
     int p;
 
-#define REGCP_OTHER_ELEMS 5
+    if (paren_elems_to_push < 0)
+       Perl_croak(aTHX_ "panic: paren_elems_to_push < 0");
+
+#define REGCP_OTHER_ELEMS 6
     SSCHECK(paren_elems_to_push + REGCP_OTHER_ELEMS);
     for (p = PL_regsize; p > parenfloor; p--) {
 /* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */
@@ -147,6 +159,7 @@ S_regcppush(pTHX_ I32 parenfloor)
 /* REGCP_OTHER_ELEMS are pushed in any case, parentheses or no. */
     SSPUSHINT(PL_regsize);
     SSPUSHINT(*PL_reglastparen);
+    SSPUSHINT(*PL_reglastcloseparen);
     SSPUSHPTR(PL_reginput);
 #define REGCP_FRAME_ELEMS 2
 /* REGCP_FRAME_ELEMS are part of the REGCP_OTHER_ELEMS and
@@ -180,6 +193,7 @@ S_regcppop(pTHX)
     assert(i == SAVEt_REGCONTEXT); /* Check that the magic cookie is there. */
     i = SSPOPINT; /* Parentheses elements to pop. */
     input = (char *) SSPOPPTR;
+    *PL_reglastcloseparen = SSPOPINT;
     *PL_reglastparen = SSPOPINT;
     PL_regsize = SSPOPINT;
 
@@ -348,17 +362,16 @@ char *
 Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
                     char *strend, U32 flags, re_scream_pos_data *data)
 {
-    register I32 start_shift;
+    register I32 start_shift = 0;
     /* Should be nonnegative! */
-    register I32 end_shift;
+    register I32 end_shift   = 0;
     register char *s;
     register SV *check;
     char *strbeg;
     char *t;
     I32 ml_anch;
-    char *tmp;
     register char *other_last = Nullch;        /* other substr checked before this */
-    char *check_at;                    /* check substr found at this pos */
+    char *check_at = Nullch;           /* check substr found at this pos */
 #ifdef DEBUGGING
     char *i_strpos = strpos;
 #endif
@@ -392,7 +405,8 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
                          && !PL_multiline ) ); /* Check after \n? */
 
        if (!ml_anch) {
-         if ( !(prog->reganch & ROPT_ANCH_GPOS) /* Checked by the caller */
+         if ( !(prog->reganch & (ROPT_ANCH_GPOS /* Checked by the caller */
+                                 | ROPT_IMPLICIT)) /* not a real BOL */
               /* SvCUR is not set on references: SvRV and SvPVX overlap */
               && sv && !SvROK(sv)
               && (strpos != strbeg)) {
@@ -400,7 +414,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
              goto fail;
          }
          if (prog->check_offset_min == prog->check_offset_max &&
-             !(prog->reganch & ROPT_SANY_SEEN)) {
+             !(prog->reganch & ROPT_CANY_SEEN)) {
            /* Substring at constant offset from beg-of-str... */
            I32 slen;
 
@@ -476,7 +490,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
        if (data)
            *data->scream_olds = s;
     }
-    else if (prog->reganch & ROPT_SANY_SEEN)
+    else if (prog->reganch & ROPT_CANY_SEEN)
        s = fbm_instr((U8*)(s + start_shift),
                      (U8*)(strend - end_shift),
                      check, PL_multiline ? FBMrf_MULTILINE : 0);
@@ -762,10 +776,10 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
            PL_regdata = prog->data;
            PL_bostr = startpos;
        }
-        s = find_byclass(prog, prog->regstclass, s, endpos, startpos, 1);
+       s = find_byclass(prog, prog->regstclass, s, endpos, startpos, 1);
        if (!s) {
 #ifdef DEBUGGING
-           char *what;
+           char *what = 0;
 #endif
            if (endpos == strend) {
                DEBUG_r( PerlIO_printf(Perl_debug_log,
@@ -826,13 +840,17 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
            DEBUG_r( what = "floating" );
            goto hop_and_restart;
        }
-       DEBUG_r( if (t != s)
-                    PerlIO_printf(Perl_debug_log,
+       if (t != s) {
+            DEBUG_r(PerlIO_printf(Perl_debug_log,
                        "By STCLASS: moving %ld --> %ld\n",
-                       (long)(t - i_strpos), (long)(s - i_strpos));
-                else
-                    PerlIO_printf(Perl_debug_log,
-                       "Does not contradict STCLASS...\n") );
+                                  (long)(t - i_strpos), (long)(s - i_strpos))
+                   );
+        }
+        else {
+            DEBUG_r(PerlIO_printf(Perl_debug_log,
+                                  "Does not contradict STCLASS...\n"); 
+                   );
+        }
     }
   giveup:
     DEBUG_r(PerlIO_printf(Perl_debug_log, "%s%s:%s match at offset %ld\n",
@@ -860,7 +878,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
        unsigned int c2;
        char *e;
        register I32 tmp = 1;   /* Scratch variable? */
-       register bool do_utf8 = DO_UTF8(PL_reg_sv);
+       register bool do_utf8 = PL_reg_sv_utf8;
 
        /* We know what class it must start with. */
        switch (OP(c)) {
@@ -877,6 +895,15 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                s += do_utf8 ? UTF8SKIP(s) : 1;
            }
            break;
+       case CANY:
+           while (s < strend) {
+               if (tmp && (norun || regtry(prog, s)))
+                   goto got_it;
+               else
+                   tmp = doevery;
+               s++;
+           }
+           break;
        case EXACTF:
            m = STRING(c);
            ln = STR_LEN(c);
@@ -945,19 +972,20 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            /* FALL THROUGH */
        case BOUND:
            if (do_utf8) {
-               if (s == startpos)
+               if (s == PL_bostr)
                    tmp = '\n';
                else {
                    U8 *r = reghop3((U8*)s, -1, (U8*)startpos);
                
-                   tmp = (I32)utf8n_to_uvuni(r, s - (char*)r, 0, 0);
+                   if (s > (char*)r)
+                       tmp = (I32)utf8n_to_uvchr(r, s - (char*)r, 0, 0);
                }
                tmp = ((OP(c) == BOUND ?
                        isALNUM_uni(tmp) : isALNUM_LC_uvchr(UNI_TO_NATIVE(tmp))) != 0);
                LOAD_UTF8_CHARCLASS(alnum,"a");
                while (s < strend) {
                    if (tmp == !(OP(c) == BOUND ?
-                                swash_fetch(PL_utf8_alnum, (U8*)s) :
+                                swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) :
                                 isALNUM_LC_utf8((U8*)s)))
                    {
                        tmp = !tmp;
@@ -968,7 +996,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                }
            }
            else {
-               tmp = (s != startpos) ? UCHARAT(s - 1) : '\n';
+               tmp = (s != PL_bostr) ? UCHARAT(s - 1) : '\n';
                tmp = ((OP(c) == BOUND ? isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
                while (s < strend) {
                    if (tmp ==
@@ -988,19 +1016,20 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            /* FALL THROUGH */
        case NBOUND:
            if (do_utf8) {
-               if (s == startpos)
+               if (s == PL_bostr)
                    tmp = '\n';
                else {
                    U8 *r = reghop3((U8*)s, -1, (U8*)startpos);
                
-                   tmp = (I32)utf8n_to_uvuni(r, s - (char*)r, 0, 0);
+                   if (s > (char*)r)
+                       tmp = (I32)utf8n_to_uvchr(r, s - (char*)r, 0, 0);
                }
                tmp = ((OP(c) == NBOUND ?
                        isALNUM_uni(tmp) : isALNUM_LC_uvchr(UNI_TO_NATIVE(tmp))) != 0);
                LOAD_UTF8_CHARCLASS(alnum,"a");
                while (s < strend) {
                    if (tmp == !(OP(c) == NBOUND ?
-                                swash_fetch(PL_utf8_alnum, (U8*)s) :
+                                swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) :
                                 isALNUM_LC_utf8((U8*)s)))
                        tmp = !tmp;
                    else if ((norun || regtry(prog, s)))
@@ -1009,7 +1038,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                }
            }
            else {
-               tmp = (s != startpos) ? UCHARAT(s - 1) : '\n';
+               tmp = (s != PL_bostr) ? UCHARAT(s - 1) : '\n';
                tmp = ((OP(c) == NBOUND ?
                        isALNUM(tmp) : isALNUM_LC(tmp)) != 0);
                while (s < strend) {
@@ -1028,7 +1057,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(alnum,"a");
                while (s < strend) {
-                   if (swash_fetch(PL_utf8_alnum, (U8*)s)) {
+                   if (swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1086,7 +1115,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(alnum,"a");
                while (s < strend) {
-                   if (!swash_fetch(PL_utf8_alnum, (U8*)s)) {
+                   if (!swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1144,7 +1173,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(space," ");
                while (s < strend) {
-                   if (*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s)) {
+                   if (*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8)) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1202,7 +1231,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(space," ");
                while (s < strend) {
-                   if (!(*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s))) {
+                   if (!(*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8))) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1260,7 +1289,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(digit,"0");
                while (s < strend) {
-                   if (swash_fetch(PL_utf8_digit,(U8*)s)) {
+                   if (swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1318,7 +1347,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(digit,"0");
                while (s < strend) {
-                   if (!swash_fetch(PL_utf8_digit,(U8*)s)) {
+                   if (!swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) {
                        if (tmp && (norun || regtry(prog, s)))
                            goto got_it;
                        else
@@ -1420,25 +1449,11 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     }
 
     minlen = prog->minlen;
-    if (do_utf8) {
-      if (!(prog->reganch & ROPT_SANY_SEEN))
+    if (do_utf8 && !(prog->reganch & ROPT_CANY_SEEN)) {
         if (utf8_distance((U8*)strend, (U8*)startpos) < minlen) goto phooey;
     }
     else {
-      if (strend - startpos < minlen) goto phooey;
-    }
-
-    if (startpos == strbeg)    /* is ^ valid at stringarg? */
-       PL_regprev = '\n';
-    else {
-        if (prog->reganch & ROPT_UTF8 && do_utf8) {
-           U8 *s = reghop3((U8*)stringarg, -1, (U8*)strbeg);
-           PL_regprev = utf8n_to_uvuni(s, (U8*)stringarg - s, NULL, 0);
-       }
-       else
-           PL_regprev = (U32)stringarg[-1];
-       if (!PL_multiline && PL_regprev == '\n')
-           PL_regprev = '\0';          /* force ^ to NOT match */
+        if (strend - startpos < minlen) goto phooey;
     }
 
     /* Check validity of program. */
@@ -1477,10 +1492,11 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            PL_reg_ganch = startpos;
        else if (sv && SvTYPE(sv) >= SVt_PVMG
                  && SvMAGIC(sv)
-                 && (mg = mg_find(sv, 'g')) && mg->mg_len >= 0) {
+                 && (mg = mg_find(sv, PERL_MAGIC_regex_global))
+                 && mg->mg_len >= 0) {
            PL_reg_ganch = strbeg + mg->mg_len; /* Defined pos() */
            if (prog->reganch & ROPT_ANCH_GPOS) {
-               if (s > PL_reg_ganch)
+               if (s > PL_reg_ganch)
                    goto phooey;
                s = PL_reg_ganch;
            }
@@ -1595,9 +1611,10 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                s++;
            }
        }
-       DEBUG_r(did_match ||
+       DEBUG_r(if (!did_match)
                PerlIO_printf(Perl_debug_log,
-                             "Did not find anchored character...\n"));
+                                  "Did not find anchored character...\n")
+               );
     }
     /*SUPPRESS 560*/
     else if (do_utf8 == (UTF!=0) &&
@@ -1661,14 +1678,16 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                }
            }
        }
-       DEBUG_r(did_match ||
-               PerlIO_printf(Perl_debug_log, "Did not find %s substr `%s%.*s%s'%s...\n",
+       DEBUG_r(if (!did_match)
+                    PerlIO_printf(Perl_debug_log, 
+                                  "Did not find %s substr `%s%.*s%s'%s...\n",
                              ((must == prog->anchored_substr)
                               ? "anchored" : "floating"),
                              PL_colors[0],
                              (int)(SvCUR(must) - (SvTAIL(must)!=0)),
                              SvPVX(must),
-                             PL_colors[1], (SvTAIL(must) ? "$" : "")));
+                                  PL_colors[1], (SvTAIL(must) ? "$" : ""))
+               );
        goto phooey;
     }
     else if ((c = prog->regstclass)) {
@@ -1828,19 +1847,31 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
            }
        
            if (!(SvTYPE(PL_reg_sv) >= SVt_PVMG && SvMAGIC(PL_reg_sv)
-                 && (mg = mg_find(PL_reg_sv, 'g')))) {
+                 && (mg = mg_find(PL_reg_sv, PERL_MAGIC_regex_global)))) {
                /* prepare for quick setting of pos */
-               sv_magic(PL_reg_sv, (SV*)0, 'g', Nullch, 0);
-               mg = mg_find(PL_reg_sv, 'g');
+               sv_magic(PL_reg_sv, (SV*)0,
+                       PERL_MAGIC_regex_global, Nullch, 0);
+               mg = mg_find(PL_reg_sv, PERL_MAGIC_regex_global);
                mg->mg_len = -1;
            }
            PL_reg_magic    = mg;
            PL_reg_oldpos   = mg->mg_len;
            SAVEDESTRUCTOR_X(restore_pos, 0);
         }
-       if (!PL_reg_curpm)
+        if (!PL_reg_curpm) {
            Newz(22,PL_reg_curpm, 1, PMOP);
-       PL_reg_curpm->op_pmregexp = prog;
+#ifdef USE_ITHREADS
+            {
+                SV* repointer = newSViv(0);
+                /* so we know which PL_regex_padav element is PL_reg_curpm */
+                SvFLAGS(repointer) |= SVf_BREAK;
+                av_push(PL_regex_padav,repointer);
+                PL_reg_curpm->op_pmoffset = av_len(PL_regex_padav);
+                PL_regex_pad = AvARRAY(PL_regex_padav);
+            }
+#endif      
+        }
+       PM_SETRE(PL_reg_curpm, prog);
        PL_reg_oldcurpm = PL_curpm;
        PL_curpm = PL_reg_curpm;
        if (RX_MATCH_COPIED(prog)) {
@@ -1861,6 +1892,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
     PL_regstartp = prog->startp;
     PL_regendp = prog->endp;
     PL_reglastparen = &prog->lastparen;
+    PL_reglastcloseparen = &prog->lastcloseparen;
     prog->lastparen = 0;
     PL_regsize = 0;
     DEBUG_r(PL_reg_starttry = startpos);
@@ -1935,6 +1967,16 @@ typedef union re_unwind_t {
     re_unwind_branch_t branch;
 } re_unwind_t;
 
+#define sayYES goto yes
+#define sayNO goto no
+#define sayYES_FINAL goto yes_final
+#define sayYES_LOUD  goto yes_loud
+#define sayNO_FINAL  goto no_final
+#define sayNO_SILENT goto do_no
+#define saySAME(x) if (x) goto yes; else goto no
+
+#define REPORT_CODE_OFF 24
+
 /*
  - regmatch - main matching routine
  *
@@ -1958,14 +2000,16 @@ S_regmatch(pTHX_ regnode *prog)
     register I32 nextchr;      /* renamed nextchr - nextchar colides with
                                   function of same name */
     register I32 n;            /* no or next */
-    register I32 ln;           /* len or last */
-    register char *s;          /* operand or save */
+    register I32 ln = 0;       /* len or last */
+    register char *s = Nullch; /* operand or save */
     register char *locinput = PL_reginput;
-    register I32 c1, c2, paren;        /* case fold search, parenth */
+    register I32 c1 = 0, c2 = 0, paren;        /* case fold search, parenth */
     int minmod = 0, sw = 0, logical = 0;
     I32 unwind = 0;
+#if 0
     I32 firstcp = PL_savestack_ix;
-    register bool do_utf8 = DO_UTF8(PL_reg_sv);
+#endif
+    register bool do_utf8 = PL_reg_sv_utf8;
 
 #ifdef DEBUGGING
     PL_regindent++;
@@ -1975,25 +2019,7 @@ S_regmatch(pTHX_ regnode *prog)
     nextchr = UCHARAT(locinput);
     scan = prog;
     while (scan != NULL) {
-#define sayNO_L (logical ? (logical = 0, sw = 0, goto cont) : sayNO)
-#if 1
-#  define sayYES goto yes
-#  define sayNO goto no
-#  define sayYES_FINAL goto yes_final
-#  define sayYES_LOUD  goto yes_loud
-#  define sayNO_FINAL  goto no_final
-#  define sayNO_SILENT goto do_no
-#  define saySAME(x) if (x) goto yes; else goto no
-#  define REPORT_CODE_OFF 24
-#else
-#  define sayYES return 1
-#  define sayNO return 0
-#  define sayYES_FINAL return 1
-#  define sayYES_LOUD  return 1
-#  define sayNO_FINAL  return 0
-#  define sayNO_SILENT return 0
-#  define saySAME(x) return x
-#endif
+
        DEBUG_r( {
            SV *prop = sv_newmortal();
            int docolor = *PL_colors[0];
@@ -2043,19 +2069,16 @@ S_regmatch(pTHX_ regnode *prog)
 
        switch (OP(scan)) {
        case BOL:
-           if (locinput == PL_bostr
-               ? PL_regprev == '\n'
-               : (PL_multiline &&
-                  (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
+           if (locinput == PL_bostr || (PL_multiline &&
+               (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
            {
                /* regtill = regbol; */
                break;
            }
            sayNO;
        case MBOL:
-           if (locinput == PL_bostr
-               ? PL_regprev == '\n'
-               : ((nextchr || locinput < PL_regeol) && locinput[-1] == '\n') )
+           if (locinput == PL_bostr ||
+               ((nextchr || locinput < PL_regeol) && locinput[-1] == '\n'))
            {
                break;
            }
@@ -2092,6 +2115,18 @@ S_regmatch(pTHX_ regnode *prog)
        case SANY:
            if (!nextchr && locinput >= PL_regeol)
                sayNO;
+           if (do_utf8) {
+               locinput += PL_utf8skip[nextchr];
+               if (locinput > PL_regeol)
+                   sayNO;
+               nextchr = UCHARAT(locinput);
+           }
+           else
+               nextchr = UCHARAT(++locinput);
+           break;
+       case CANY:
+           if (!nextchr && locinput >= PL_regeol)
+               sayNO;
            nextchr = UCHARAT(++locinput);
            break;
        case REG_ANY:
@@ -2161,7 +2196,7 @@ S_regmatch(pTHX_ regnode *prog)
                    if (l >= PL_regeol) {
                        sayNO;
                    }
-                   if ((UTF ? utf8n_to_uvuni((U8*)s, e - s, 0, 0) : *((U8*)s)) !=
+                   if ((UTF ? utf8n_to_uvchr((U8*)s, e - s, 0, 0) : *((U8*)s)) !=
                        (c1 ? toLOWER_utf8((U8*)l) : toLOWER_LC_utf8((U8*)l)))
                            sayNO;
                    s += UTF ? UTF8SKIP(s) : 1;
@@ -2212,8 +2247,9 @@ S_regmatch(pTHX_ regnode *prog)
            if (!nextchr)
                sayNO;
            if (do_utf8) {
+               LOAD_UTF8_CHARCLASS(alnum,"a");
                if (!(OP(scan) == ALNUM
-                     ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
+                     ? swash_fetch(PL_utf8_alnum, (U8*)locinput, do_utf8)
                      : isALNUM_LC_utf8((U8*)locinput)))
                {
                    sayNO;
@@ -2236,7 +2272,7 @@ S_regmatch(pTHX_ regnode *prog)
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(alnum,"a");
                if (OP(scan) == NALNUM
-                   ? swash_fetch(PL_utf8_alnum, (U8*)locinput)
+                   ? swash_fetch(PL_utf8_alnum, (U8*)locinput, do_utf8)
                    : isALNUM_LC_utf8((U8*)locinput))
                {
                    sayNO;
@@ -2258,17 +2294,17 @@ S_regmatch(pTHX_ regnode *prog)
        case NBOUND:
            /* was last char in word? */
            if (do_utf8) {
-               if (locinput == PL_regbol)
-                   ln = PL_regprev;
+               if (locinput == PL_bostr)
+                   ln = '\n';
                else {
                    U8 *r = reghop((U8*)locinput, -1);
                
-                   ln = utf8n_to_uvuni(r, s - (char*)r, 0, 0);
+                   ln = utf8n_to_uvchr(r, s - (char*)r, 0, 0);
                }
                if (OP(scan) == BOUND || OP(scan) == NBOUND) {
                    ln = isALNUM_uni(ln);
                    LOAD_UTF8_CHARCLASS(alnum,"a");
-                   n = swash_fetch(PL_utf8_alnum, (U8*)locinput);
+                   n = swash_fetch(PL_utf8_alnum, (U8*)locinput, do_utf8);
                }
                else {
                    ln = isALNUM_LC_uvchr(UNI_TO_NATIVE(ln));
@@ -2276,8 +2312,8 @@ S_regmatch(pTHX_ regnode *prog)
                }
            }
            else {
-               ln = (locinput != PL_regbol) ?
-                   UCHARAT(locinput - 1) : PL_regprev;
+               ln = (locinput != PL_bostr) ?
+                   UCHARAT(locinput - 1) : '\n';
                if (OP(scan) == BOUND || OP(scan) == NBOUND) {
                    ln = isALNUM(ln);
                    n = isALNUM(nextchr);
@@ -2301,7 +2337,7 @@ S_regmatch(pTHX_ regnode *prog)
                if (UTF8_IS_CONTINUED(nextchr)) {
                    LOAD_UTF8_CHARCLASS(space," ");
                    if (!(OP(scan) == SPACE
-                         ? swash_fetch(PL_utf8_space, (U8*)locinput)
+                         ? swash_fetch(PL_utf8_space, (U8*)locinput, do_utf8)
                          : isSPACE_LC_utf8((U8*)locinput)))
                    {
                        sayNO;
@@ -2331,7 +2367,7 @@ S_regmatch(pTHX_ regnode *prog)
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(space," ");
                if (OP(scan) == NSPACE
-                   ? swash_fetch(PL_utf8_space, (U8*)locinput)
+                   ? swash_fetch(PL_utf8_space, (U8*)locinput, do_utf8)
                    : isSPACE_LC_utf8((U8*)locinput))
                {
                    sayNO;
@@ -2354,7 +2390,7 @@ S_regmatch(pTHX_ regnode *prog)
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(digit,"0");
                if (!(OP(scan) == DIGIT
-                     ? swash_fetch(PL_utf8_digit, (U8*)locinput)
+                     ? swash_fetch(PL_utf8_digit, (U8*)locinput, do_utf8)
                      : isDIGIT_LC_utf8((U8*)locinput)))
                {
                    sayNO;
@@ -2377,7 +2413,7 @@ S_regmatch(pTHX_ regnode *prog)
            if (do_utf8) {
                LOAD_UTF8_CHARCLASS(digit,"0");
                if (OP(scan) == NDIGIT
-                   ? swash_fetch(PL_utf8_digit, (U8*)locinput)
+                   ? swash_fetch(PL_utf8_digit, (U8*)locinput, do_utf8)
                    : isDIGIT_LC_utf8((U8*)locinput))
                {
                    sayNO;
@@ -2393,10 +2429,12 @@ S_regmatch(pTHX_ regnode *prog)
            break;
        case CLUMP:
            LOAD_UTF8_CHARCLASS(mark,"~");
-           if (locinput >= PL_regeol || swash_fetch(PL_utf8_mark,(U8*)locinput))
+           if (locinput >= PL_regeol ||
+               swash_fetch(PL_utf8_mark,(U8*)locinput, do_utf8))
                sayNO;
            locinput += PL_utf8skip[nextchr];
-           while (locinput < PL_regeol && swash_fetch(PL_utf8_mark,(U8*)locinput))
+           while (locinput < PL_regeol &&
+                  swash_fetch(PL_utf8_mark,(U8*)locinput, do_utf8))
                locinput += UTF8SKIP(locinput);
            if (locinput > PL_regeol)
                sayNO;
@@ -2506,7 +2544,7 @@ S_regmatch(pTHX_ regnode *prog)
                        SV *sv = SvROK(ret) ? SvRV(ret) : ret;
 
                        if(SvMAGICAL(sv))
-                           mg = mg_find(sv, 'r');
+                           mg = mg_find(sv, PERL_MAGIC_qr);
                    }
                    if (mg) {
                        re = (regexp *)mg->mg_obj;
@@ -2520,11 +2558,12 @@ S_regmatch(pTHX_ regnode *prog)
                        I32 osize = PL_regsize;
                        I32 onpar = PL_regnpar;
 
-                       pm.op_pmflags = 0;
+                       Zero(&pm, 1, PMOP);
                        re = CALLREGCOMP(aTHX_ t, t + len, &pm);
                        if (!(SvFLAGS(ret)
                              & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)))
-                           sv_magic(ret,(SV*)ReREFCNT_inc(re),'r',0,0);
+                           sv_magic(ret,(SV*)ReREFCNT_inc(re),
+                                       PERL_MAGIC_qr,0,0);
                        PL_regprecomp = oprecomp;
                        PL_regsize = osize;
                        PL_regnpar = onpar;
@@ -2549,6 +2588,7 @@ S_regmatch(pTHX_ regnode *prog)
                    cache_re(re);
                    state.ss = PL_savestack_ix;
                    *PL_reglastparen = 0;
+                   *PL_reglastcloseparen = 0;
                    PL_reg_call_cc = &state;
                    PL_reginput = locinput;
 
@@ -2585,6 +2625,7 @@ S_regmatch(pTHX_ regnode *prog)
                    /* XXXX This is too dramatic a measure... */
                    PL_reg_maxiter = 0;
 
+                   logical = 0;
                    sayNO;
                }
                sw = SvTRUE(ret);
@@ -2606,6 +2647,7 @@ S_regmatch(pTHX_ regnode *prog)
            PL_regendp[n] = locinput - PL_bostr;
            if (n > *PL_reglastparen)
                *PL_reglastparen = n;
+           *PL_reglastcloseparen = n;
            break;
        case GROUPP:
            n = ARG(scan);  /* which paren pair */
@@ -2932,7 +2974,6 @@ S_regmatch(pTHX_ regnode *prog)
            inner = NEXTOPER(scan);
          do_branch:
            {
-               CHECKPOINT lastcp;
                c1 = OP(scan);
                if (OP(next) != c1)     /* No choice. */
                    next = inner;       /* Avoid recursion. */
@@ -2992,12 +3033,15 @@ S_regmatch(pTHX_ regnode *prog)
                minmod = 0;
                if (ln && regrepeat_hard(scan, ln, &l) < ln)
                    sayNO;
-               if (ln && l == 0 && n >= ln
-                   /* In fact, this is tricky.  If paren, then the
-                      fact that we did/didnot match may influence
-                      future execution. */
-                   && !(paren && ln == 0))
-                   ln = n;
+               /* if we matched something zero-length we don't need to
+                  backtrack - capturing parens are already defined, so
+                  the caveat in the maximal case doesn't apply
+
+                  XXXX if ln == 0, we can redo this check first time
+                  through the following loop
+               */
+               if (ln && l == 0)
+                   n = ln;     /* don't backtrack */
                locinput = PL_reginput;
                if (PL_regkind[(U8)OP(next)] == EXACT) {
                    c1 = (U8)*STRING(next);
@@ -3019,7 +3063,7 @@ S_regmatch(pTHX_ regnode *prog)
                        UCHARAT(PL_reginput) == c2)
                    {
                        if (paren) {
-                           if (n) {
+                           if (ln) {
                                PL_regstartp[paren] =
                                    HOPc(PL_reginput, -l) - PL_bostr;
                                PL_regendp[paren] = PL_reginput - PL_bostr;
@@ -3043,12 +3087,13 @@ S_regmatch(pTHX_ regnode *prog)
            }
            else {
                n = regrepeat_hard(scan, n, &l);
-               if (n != 0 && l == 0
-                   /* In fact, this is tricky.  If paren, then the
-                      fact that we did/didnot match may influence
-                      future execution. */
-                   && !(paren && ln == 0))
-                   ln = n;
+               /* if we matched something zero-length we don't need to
+                  backtrack, unless the minimum count is zero and we
+                  are capturing the result - in that case the capture
+                  being defined or not may affect later execution
+               */
+               if (n != 0 && l == 0 && !(paren && ln == 0))
+                   ln = n;     /* don't backtrack */
                locinput = PL_reginput;
                DEBUG_r(
                    PerlIO_printf(Perl_debug_log,
@@ -3245,9 +3290,15 @@ S_regmatch(pTHX_ regnode *prog)
                            c = utf8_to_uvchr((U8*)PL_reginput, NULL);
                        else
                            c = UCHARAT(PL_reginput);
+                       /* If it could work, try it. */
+                       if (c == c1 || c == c2)
+                       {
+                           TRYPAREN(paren, n, PL_reginput);
+                           REGCP_UNWIND(lastcp);
+                       }
                    }
                    /* If it could work, try it. */
-                   if (c1 == -1000 || c == c1 || c == c2)
+                   else if (c1 == -1000)
                    {
                        TRYPAREN(paren, n, PL_reginput);
                        REGCP_UNWIND(lastcp);
@@ -3277,7 +3328,7 @@ S_regmatch(pTHX_ regnode *prog)
                }
                REGCP_SET(lastcp);
                if (paren) {
-                   UV c;
+                   UV c = 0;
                    while (n >= ln) {
                        if (c1 != -1000) {
                            if (do_utf8)
@@ -3297,7 +3348,7 @@ S_regmatch(pTHX_ regnode *prog)
                    }
                }
                else {
-                   UV c;
+                   UV c = 0;
                    while (n >= ln) {
                        if (c1 != -1000) {
                            if (do_utf8)
@@ -3375,20 +3426,10 @@ S_regmatch(pTHX_ regnode *prog)
        case UNLESSM:
            n = 0;
            if (scan->flags) {
-               if (UTF) {              /* XXXX This is absolutely
-                                          broken, we read before
-                                          start of string. */
-                   s = HOPMAYBEc(locinput, -scan->flags);
-                   if (!s)
-                       goto say_yes;
-                   PL_reginput = s;
-               }
-               else {
-                   if (locinput < PL_bostr + scan->flags)
-                       goto say_yes;
-                   PL_reginput = locinput - scan->flags;
-                   goto do_ifmatch;
-               }
+               s = HOPBACKc(locinput, scan->flags);
+               if (!s)
+                   goto say_yes;
+               PL_reginput = s;
            }
            else
                PL_reginput = locinput;
@@ -3396,20 +3437,10 @@ S_regmatch(pTHX_ regnode *prog)
        case IFMATCH:
            n = 1;
            if (scan->flags) {
-               if (UTF) {              /* XXXX This is absolutely
-                                          broken, we read before
-                                          start of string. */
-                   s = HOPMAYBEc(locinput, -scan->flags);
-                   if (!s || s < PL_bostr)
-                       goto say_no;
-                   PL_reginput = s;
-               }
-               else {
-                   if (locinput < PL_bostr + scan->flags)
-                       goto say_no;
-                   PL_reginput = locinput - scan->flags;
-                   goto do_ifmatch;
-               }
+               s = HOPBACKc(locinput, scan->flags);
+               if (!s)
+                   goto say_no;
+               PL_reginput = s;
            }
            else
                PL_reginput = locinput;
@@ -3559,7 +3590,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
     register I32 c;
     register char *loceol = PL_regeol;
     register I32 hardcount = 0;
-    register bool do_utf8 = DO_UTF8(PL_reg_sv);
+    register bool do_utf8 = PL_reg_sv_utf8;
 
     scan = PL_reginput;
     if (max != REG_INFTY && max < loceol - scan)
@@ -3580,6 +3611,9 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
     case SANY:
        scan = loceol;
        break;
+    case CANY:
+       scan = loceol;
+       break;
     case EXACT:                /* length of string is 1 */
        c = (U8)*STRING(p);
        while (scan < loceol && UCHARAT(scan) == c)
@@ -3616,7 +3650,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(alnum,"a");
            while (hardcount < max && scan < loceol &&
-                  swash_fetch(PL_utf8_alnum, (U8*)scan)) {
+                  swash_fetch(PL_utf8_alnum, (U8*)scan, do_utf8)) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3644,7 +3678,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(alnum,"a");
            while (hardcount < max && scan < loceol &&
-                  !swash_fetch(PL_utf8_alnum, (U8*)scan)) {
+                  !swash_fetch(PL_utf8_alnum, (U8*)scan, do_utf8)) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3672,7 +3706,8 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(space," ");
            while (hardcount < max && scan < loceol &&
-                  (*scan == ' ' || swash_fetch(PL_utf8_space,(U8*)scan))) {
+                  (*scan == ' ' ||
+                   swash_fetch(PL_utf8_space,(U8*)scan, do_utf8))) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3700,7 +3735,8 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(space," ");
            while (hardcount < max && scan < loceol &&
-                  !(*scan == ' ' || swash_fetch(PL_utf8_space,(U8*)scan))) {
+                  !(*scan == ' ' ||
+                    swash_fetch(PL_utf8_space,(U8*)scan, do_utf8))) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3728,7 +3764,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(digit,"0");
            while (hardcount < max && scan < loceol &&
-                  swash_fetch(PL_utf8_digit,(U8*)scan)) {
+                  swash_fetch(PL_utf8_digit, (U8*)scan, do_utf8)) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3742,7 +3778,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
            loceol = PL_regeol;
            LOAD_UTF8_CHARCLASS(digit,"0");
            while (hardcount < max && scan < loceol &&
-                  !swash_fetch(PL_utf8_digit,(U8*)scan)) {
+                  !swash_fetch(PL_utf8_digit, (U8*)scan, do_utf8)) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
@@ -3783,7 +3819,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
 STATIC I32
 S_regrepeat_hard(pTHX_ regnode *p, I32 max, I32 *lp)
 {
-    register char *scan;
+    register char *scan = Nullch;
     register char *start;
     register char *loceol = PL_regeol;
     I32 l = 0;
@@ -3793,7 +3829,7 @@ S_regrepeat_hard(pTHX_ regnode *p, I32 max, I32 *lp)
        return 0;
 
     start = PL_reginput;
-    if (DO_UTF8(PL_reg_sv)) {
+    if (PL_reg_sv_utf8) {
        while (PL_reginput < loceol && (scan = PL_reginput, res = regmatch(p))) {
            if (!count++) {
                l = 0;
@@ -3872,25 +3908,22 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
     char flags = ANYOF_FLAGS(n);
     bool match = FALSE;
     UV c;
-    STRLEN len;
+    STRLEN len = 0;
 
-    if (do_utf8)
-       c = utf8_to_uvchr(p, &len);
-    else
-       c = *p;
+    c = do_utf8 ? utf8_to_uvchr(p, &len) : *p;
 
     if (do_utf8 || (flags & ANYOF_UNICODE)) {
        if (do_utf8 && !ANYOF_RUNTIME(n)) {
            if (len != (STRLEN)-1 && c < 256 && ANYOF_BITMAP_TEST(n, c))
                match = TRUE;
        }
-       if (do_utf8 && flags & ANYOF_UNICODE_ALL && c >= 256)
+       if (!match && do_utf8 && (flags & ANYOF_UNICODE_ALL) && c >= 256)
            match = TRUE;
        if (!match) {
            SV *sw = regclass_swash(n, TRUE, 0);
        
            if (sw) {
-               if (swash_fetch(sw, p))
+               if (swash_fetch(sw, p, do_utf8))
                    match = TRUE;
                else if (flags & ANYOF_FOLD) {
                    U8 tmpbuf[UTF8_MAXLEN+1];
@@ -3901,7 +3934,7 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
                    }
                    else
                        uvchr_to_utf8(tmpbuf, toLOWER_utf8(p));
-                   if (swash_fetch(sw, tmpbuf))
+                   if (swash_fetch(sw, tmpbuf, do_utf8))
                        match = TRUE;
                }
            }
@@ -3911,7 +3944,7 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
        if (ANYOF_BITMAP_TEST(n, c))
            match = TRUE;
        else if (flags & ANYOF_FOLD) {
-           I32 f;
+         I32 f;
 
            if (flags & ANYOF_LOCALE) {
                PL_reg_flags |= RF_tainted;