Upgrade to I18N::LangTags 0.30.
[p5sagit/p5-mst-13.2.git] / regexec.c
index df96924..728b1ae 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -68,7 +68,7 @@
  ****    Alterations to Henry's code are...
  ****
  ****    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- ****    2000, 2001, 2002, 2003, by Larry Wall and others
+ ****    2000, 2001, 2002, 2003, 2004, 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.
@@ -87,6 +87,7 @@
 #define RF_warned      2               /* warned about big count? */
 #define RF_evaled      4               /* Did an EVAL with setting? */
 #define RF_utf8                8               /* String contains multibyte chars? */
+#define RF_false       16              /* odd number of nested negatives */
 
 #define UTF ((PL_reg_flags & RF_utf8) != 0)
 
@@ -952,6 +953,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
        I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
        char *m;
        STRLEN ln;
+       STRLEN lnc;
        unsigned int c1;
        unsigned int c2;
        char *e;
@@ -1007,10 +1009,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            }
            break;
        case EXACTF:
-           m = STRING(c);
-           ln = STR_LEN(c);
+           m   = STRING(c);
+           ln  = STR_LEN(c);   /* length to match in octets/bytes */
+           lnc = (I32) ln;     /* length to match in characters */
            if (UTF) {
                STRLEN ulen1, ulen2;
+               U8 *sm = (U8 *) m;
                U8 tmpbuf1[UTF8_MAXLEN_UCLC+1];
                U8 tmpbuf2[UTF8_MAXLEN_UCLC+1];
 
@@ -1021,6 +1025,11 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                                    0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
                c2 = utf8n_to_uvchr(tmpbuf2, UTF8_MAXLEN_UCLC,
                                    0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
+               lnc = 0;
+               while (sm < ((U8 *) m + ln)) {
+                   lnc++;
+                   sm += UTF8SKIP(sm);
+               }
            }
            else {
                c1 = *(U8*)m;
@@ -1028,12 +1037,13 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            }
            goto do_exactf;
        case EXACTFL:
-           m = STRING(c);
-           ln = STR_LEN(c);
+           m   = STRING(c);
+           ln  = STR_LEN(c);
+           lnc = (I32) ln;
            c1 = *(U8*)m;
            c2 = PL_fold_locale[c1];
          do_exactf:
-           e = HOP3c(strend, -(I32)ln, s);
+           e = HOP3c(strend, -((I32)lnc), s);
 
            if (norun && e < s)
                e = s;                  /* Due to minlen logic of intuit() */
@@ -1056,6 +1066,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                STRLEN len, foldlen;
                
                if (c1 == c2) {
+                   /* Upper and lower of 1st char are equal -
+                    * probably not a "letter". */
                    while (s <= e) {
                        c = utf8n_to_uvchr((U8*)s, UTF8_MAXLEN, &len,
                                           ckWARN(WARN_UTF8) ?
@@ -2092,8 +2104,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
        if (PL_reg_sv) {
            /* Make $_ available to executed code. */
            if (PL_reg_sv != DEFSV) {
-               /* SAVE_DEFSV does *not* suffice here for USE_5005THREADS */
-               SAVESPTR(DEFSV);
+               SAVE_DEFSV;
                DEFSV = PL_reg_sv;
            }
        
@@ -3204,7 +3215,10 @@ S_regmatch(pTHX_ regnode *prog)
                                      "%*s  already tried at this position...\n",
                                      REPORT_CODE_OFF+PL_regindent*2, "")
                        );
-                       sayNO_SILENT;
+                       if (PL_reg_flags & RF_false)
+                           sayYES;
+                       else
+                           sayNO_SILENT;
                    }
                    PL_reg_poscache[o] |= (1<<b);
                }
@@ -3353,7 +3367,7 @@ S_regmatch(pTHX_ regnode *prog)
            CHECKPOINT lastcp;
        
            /* We suppose that the next guy does not need
-              backtracking: in particular, it is of constant length,
+              backtracking: in particular, it is of constant non-zero length,
               and has no parenths to influence future backrefs. */
            ln = ARG1(scan);  /* min to match */
            n  = ARG2(scan);  /* max to match */
@@ -3372,15 +3386,6 @@ S_regmatch(pTHX_ regnode *prog)
                minmod = 0;
                if (ln && regrepeat_hard(scan, ln, &l) < ln)
                    sayNO;
-               /* 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 (HAS_TEXT(next) || JUMPABLE(next)) {
                    regnode *text_node = next;
@@ -3406,8 +3411,7 @@ S_regmatch(pTHX_ regnode *prog)
                    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 ? */
+               while (n >= ln || (n == REG_INFTY && ln > 0)) { /* ln overflow ? */
                    /* If it could work, try it. */
                    if (c1 == -1000 ||
                        UCHARAT(PL_reginput) == c1 ||
@@ -3438,13 +3442,6 @@ S_regmatch(pTHX_ regnode *prog)
            }
            else {
                n = regrepeat_hard(scan, n, &l);
-               /* 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,
@@ -3854,6 +3851,7 @@ S_regmatch(pTHX_ regnode *prog)
            }
            else
                PL_reginput = locinput;
+           PL_reg_flags ^= RF_false;
            goto do_ifmatch;
        case IFMATCH:
            n = 1;
@@ -3869,6 +3867,8 @@ S_regmatch(pTHX_ regnode *prog)
          do_ifmatch:
            inner = NEXTOPER(NEXTOPER(scan));
            if (regmatch(inner) != n) {
+               if (n == 0)
+                   PL_reg_flags ^= RF_false;
              say_no:
                if (logical) {
                    logical = 0;
@@ -3878,6 +3878,8 @@ S_regmatch(pTHX_ regnode *prog)
                else
                    sayNO;
            }
+           if (n == 0)
+               PL_reg_flags ^= RF_false;
          say_yes:
            if (logical) {
                logical = 0;
@@ -4244,7 +4246,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max)
 /*
  - regrepeat_hard - repeatedly match something, report total lenth and length
  *
- * The repeater is supposed to have constant length.
+ * The repeater is supposed to have constant non-zero length.
  */
 
 STATIC I32