VERSIONize.
[p5sagit/p5-mst-13.2.git] / regexec.c
index 198e99e..4904e57 100644 (file)
--- a/regexec.c
+++ b/regexec.c
 /* for use after a quantifier and before an EXACT-like node -- japhy */
 #define JUMPABLE(rn) ( \
     OP(rn) == OPEN || OP(rn) == CLOSE || OP(rn) == EVAL || \
-    OP(rn) == SUSPEND || OP(rn) == IFMATCH \
+    OP(rn) == SUSPEND || OP(rn) == IFMATCH || \
+    OP(rn) == PLUS || OP(rn) == MINMOD || \
+    (PL_regkind[(U8)OP(rn)] == CURLY && ARG1(rn) > 0) \
 )
 
-#define NEAR_EXACT(rn) (PL_regkind[(U8)OP(rn)] == EXACT || JUMPABLE(rn))
+#define HAS_TEXT(rn) ( \
+    PL_regkind[(U8)OP(rn)] == EXACT || PL_regkind[(U8)OP(rn)] == REF \
+)
 
-#define NEXT_IMPT(rn) STMT_START { \
+#define FIND_NEXT_IMPT(rn) STMT_START { \
     while (JUMPABLE(rn)) \
-       if (OP(rn) == SUSPEND || OP(rn) == IFMATCH) \
+       if (OP(rn) == SUSPEND || OP(rn) == IFMATCH || \
+           PL_regkind[(U8)OP(rn)] == CURLY) \
            rn = NEXTOPER(NEXTOPER(rn)); \
+       else if (OP(rn) == PLUS) \
+           rn = NEXTOPER(rn); \
        else rn += NEXT_OFF(rn); \
 } STMT_END 
 
@@ -408,7 +415,8 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
        PL_reg_flags |= RF_utf8;
 
     if (prog->minlen > CHR_DIST((U8*)strend, (U8*)strpos)) {
-       DEBUG_r(PerlIO_printf(Perl_debug_log, "String too short...\n"));
+       DEBUG_r(PerlIO_printf(Perl_debug_log,
+                             "String too short... [re_intuit_start]\n"));
        goto fail;
     }
     strbeg = (sv && SvPOK(sv)) ? strend - SvCUR(sv) : strpos;
@@ -1474,19 +1482,10 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     }
 
     minlen = prog->minlen;
-    if (do_utf8 && !(prog->reganch & ROPT_CANY_SEEN)) {
-        if (utf8_distance((U8*)strend, (U8*)startpos) < minlen) {
-           DEBUG_r(PerlIO_printf(Perl_debug_log,
-                                 "Too short (in characters)...\n"));
-           goto phooey;
-       }
-    }
-    else {
-        if (strend - startpos < minlen) {
-           DEBUG_r(PerlIO_printf(Perl_debug_log,
-                                 "Too short (in bytes)...\n"));
-           goto phooey;
-       }
+    if (strend - startpos < minlen) {
+        DEBUG_r(PerlIO_printf(Perl_debug_log,
+                             "String too short [regexec_flags]...\n"));
+       goto phooey;
     }
 
     /* Check validity of program. */
@@ -2212,31 +2211,40 @@ S_regmatch(pTHX_ regnode *prog)
            s = STRING(scan);
            ln = STR_LEN(scan);
            if (do_utf8 != (UTF!=0)) {
+               /* The target and the pattern have differing "utf8ness". */
                char *l = locinput;
                char *e = s + ln;
                STRLEN len;
-               if (do_utf8)
+
+               if (do_utf8) {
+                   /* The target is utf8, the pattern is not utf8. */
                    while (s < e) {
                        if (l >= PL_regeol)
-                           sayNO;
-                       if (*((U8*)s) != utf8_to_uvchr((U8*)l, &len))
-                           sayNO;
-                       s += len;
+                            sayNO;
+                       if (NATIVE_TO_UNI(*(U8*)s) !=
+                           utf8_to_uvchr((U8*)l, &len))
+                            sayNO;
                        l += len;
+                       s ++;
                    }
-               else
+               }
+               else {
+                   /* The target is not utf8, the pattern is utf8. */
                    while (s < e) {
                        if (l >= PL_regeol)
                            sayNO;
-                       if (*((U8*)l) != utf8_to_uvchr((U8*)s, &len))
+                       if (NATIVE_TO_UNI(*((U8*)l)) !=
+                           utf8_to_uvchr((U8*)s, &len))
                            sayNO;
-                       s+=len;
-                       l++;
+                       s += len;
+                       l ++;
                    }
+               }
                locinput = l;
                nextchr = UCHARAT(locinput);
                break;
            }
+           /* The target and the pattern have the same "utf8ness". */
            /* Inline the first character, for speed. */
            if (UCHARAT(s) != nextchr)
                sayNO;
@@ -3112,17 +3120,29 @@ S_regmatch(pTHX_ regnode *prog)
                if (ln && l == 0)
                    n = ln;     /* don't backtrack */
                locinput = PL_reginput;
-               if (NEAR_EXACT(next)) {
+               if (HAS_TEXT(next) || JUMPABLE(next)) {
                    regnode *text_node = next;
 
-                   if (PL_regkind[(U8)OP(next)] != EXACT)
-                       NEXT_IMPT(text_node);
+                   if (! HAS_TEXT(text_node)) FIND_NEXT_IMPT(text_node);
 
-                   if (PL_regkind[(U8)OP(text_node)] != EXACT) {
-                       c1 = c2 = -1000;
-                   }
+                   if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                    else {
-                       c1 = (U8)*STRING(text_node);
+                       if (PL_regkind[(U8)OP(text_node)] == REF) {
+                           I32 n, ln;
+                           n = ARG(text_node);  /* which paren pair */
+                           ln = PL_regstartp[n];
+                           /* assume yes if we haven't seen CLOSEn */
+                           if (
+                               *PL_reglastparen < n ||
+                               ln == -1 ||
+                               ln == PL_regendp[n]
+                           ) {
+                               c1 = c2 = -1000;
+                               goto assume_ok_MM;
+                           }
+                           c1 = *(PL_bostr + ln);
+                       }
+                       else { c1 = (U8)*STRING(text_node); }
                        if (OP(next) == EXACTF)
                            c2 = PL_fold[c1];
                        else if (OP(text_node) == EXACTFL)
@@ -3133,6 +3153,7 @@ S_regmatch(pTHX_ regnode *prog)
                }
                else
                    c1 = c2 = -1000;
+           assume_ok_MM:
                REGCP_SET(lastcp);
                /* This may be improved if l == 0.  */
                while (n >= ln || (n == REG_INFTY && ln > 0 && l)) { /* ln overflow ? */
@@ -3181,17 +3202,30 @@ S_regmatch(pTHX_ regnode *prog)
                                  (IV) n, (IV)l)
                    );
                if (n >= ln) {
-                   if (NEAR_EXACT(next)) {
+                   if (HAS_TEXT(next) || JUMPABLE(next)) {
                        regnode *text_node = next;
 
-                       if (PL_regkind[(U8)OP(next)] != EXACT)
-                           NEXT_IMPT(text_node);
+                       if (! HAS_TEXT(text_node)) FIND_NEXT_IMPT(text_node);
 
-                       if (PL_regkind[(U8)OP(text_node)] != EXACT) {
-                           c1 = c2 = -1000;
-                       }
+                       if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                        else {
-                           c1 = (U8)*STRING(text_node);
+                           if (PL_regkind[(U8)OP(text_node)] == REF) {
+                               I32 n, ln;
+                               n = ARG(text_node);  /* which paren pair */
+                               ln = PL_regstartp[n];
+                               /* assume yes if we haven't seen CLOSEn */
+                               if (
+                                   *PL_reglastparen < n ||
+                                   ln == -1 ||
+                                   ln == PL_regendp[n]
+                               ) {
+                                   c1 = c2 = -1000;
+                                   goto assume_ok_REG;
+                               }
+                               c1 = *(PL_bostr + ln);
+                           }
+                           else { c1 = (U8)*STRING(text_node); }
+
                            if (OP(text_node) == EXACTF)
                                c2 = PL_fold[c1];
                            else if (OP(text_node) == EXACTFL)
@@ -3203,6 +3237,7 @@ S_regmatch(pTHX_ regnode *prog)
                    else
                        c1 = c2 = -1000;
                }
+           assume_ok_REG:
                REGCP_SET(lastcp);
                while (n >= ln) {
                    /* If it could work, try it. */
@@ -3275,18 +3310,30 @@ S_regmatch(pTHX_ regnode *prog)
            * of the quantifier and the EXACT-like node.  -- japhy
            */
 
-           if (NEAR_EXACT(next)) {
+           if (HAS_TEXT(next) || JUMPABLE(next)) {
                U8 *s;
                regnode *text_node = next;
 
-               if (PL_regkind[(U8)OP(next)] != EXACT)
-                   NEXT_IMPT(text_node);
+               if (! HAS_TEXT(text_node)) FIND_NEXT_IMPT(text_node);
 
-               if (PL_regkind[(U8)OP(text_node)] != EXACT) {
-                   c1 = c2 = -1000;
-               }
+               if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                else {
-                   s = (U8*)STRING(text_node);
+                   if (PL_regkind[(U8)OP(text_node)] == REF) {
+                       I32 n, ln;
+                       n = ARG(text_node);  /* which paren pair */
+                       ln = PL_regstartp[n];
+                       /* assume yes if we haven't seen CLOSEn */
+                       if (
+                           *PL_reglastparen < n ||
+                           ln == -1 ||
+                           ln == PL_regendp[n]
+                       ) {
+                           c1 = c2 = -1000;
+                           goto assume_ok_easy;
+                       }
+                       s = PL_bostr + ln;
+                   }
+                   else { s = (U8*)STRING(text_node); }
 
                    if (!UTF) {
                        c2 = c1 = *s;
@@ -3315,6 +3362,7 @@ S_regmatch(pTHX_ regnode *prog)
            }
            else
                c1 = c2 = -1000;
+       assume_ok_easy:
            PL_reginput = locinput;
            if (minmod) {
                CHECKPOINT lastcp;