[REPATCH] Re: [PATCH] Re: socketpair blip on unicos/mk, too
[p5sagit/p5-mst-13.2.git] / regexec.c
index c932165..5f25888 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -960,57 +960,86 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            c1 = *(U8*)m;
            c2 = PL_fold_locale[c1];
          do_exactf:
-           e = strend - ln;
+           e = do_utf8 ? s + ln : strend - ln;
 
            if (norun && e < s)
                e = s;                  /* Due to minlen logic of intuit() */
 
+           /* The idea in the EXACTF* cases is to first find the
+            * first character of the EXACTF* node and then, if
+            * necessary, case-insensitively compare the full
+            * text of the node.  The c1 and c2 are the first
+            * characters (though in Unicode it gets a bit
+            * more complicated because there are more cases
+            * than just upper and lower: one is really supposed
+            * to use the so-called folding case for case-insensitive
+            * matching (called "loose matching" in Unicode).  */
+
            if (do_utf8) {
                UV c, f;
                U8 tmpbuf [UTF8_MAXLEN+1];
                U8 foldbuf[UTF8_MAXLEN_FOLD+1];
                STRLEN len, foldlen;
-
-               /* The ibcmp_utf8() uses to_uni_fold() which is more
-                * correct folding for Unicode than using lowercase.
-                * However, it doesn't work quite fully since the folding
-                * is a one-to-many mapping and the regex optimizer is
-                * unaware of this, so it may throw out good matches.
-                * Fortunately, not getting this right is allowed
-                * for Unicode Regular Expression Support level 1,
-                * only one-to-one matching is required. --jhi */
+               
                if (c1 == c2) {
                    while (s <= e) {
                        c = utf8_to_uvchr((U8*)s, &len);
-                       uvchr_to_utf8(tmpbuf, c);
-                       to_utf8_fold(tmpbuf, foldbuf, &foldlen);
-                       f = utf8_to_uvchr(foldbuf, 0);
-                       
-                       if ( ((c == c1 && ln == len) ||
-                             (f == c1 && ln == foldlen) ||
-                             !ibcmp_utf8(s, do_utf8, (I32)(strend - s),
-                                         m, UTF, (I32)ln))
+                       if ( c == c1
+                            && (ln == len ||
+                                ibcmp_utf8(s, (char **)0, 0,  do_utf8,
+                                           m, (char **)0, ln, UTF))
                             && (norun || regtry(prog, s)) )
                            goto got_it;
+                       else {
+                            uvchr_to_utf8(tmpbuf, c);
+                            f = to_utf8_fold(tmpbuf, foldbuf, &foldlen);
+                            if ( f != c
+                                 && (f == c1 || f == c2)
+                                 && (ln == foldlen ||
+                                     !ibcmp_utf8((char *) foldbuf,
+                                                 (char **)0, foldlen, do_utf8,
+                                                 m,
+                                                 (char **)0, ln,      UTF))
+                                 && (norun || regtry(prog, s)) )
+                                 goto got_it;
+                       }
                        s += len;
                    }
                }
                else {
                    while (s <= e) {
                        c = utf8_to_uvchr((U8*)s, &len);
-                       uvchr_to_utf8(tmpbuf, c);
-                       to_utf8_fold(tmpbuf, foldbuf, &foldlen);
-                       f = utf8_to_uvchr(foldbuf, 0);
-                       
+
+                       /* Handle some of the three Greek sigmas cases.
+                         * Note that not all the possible combinations
+                         * are handled here: some of them are handled
+                         * handled by the standard folding rules, and
+                         * some of them (the character class or ANYOF
+                         * cases) are handled during compiletime in
+                         * regexec.c:S_regclass(). */
                        if (c == (UV)UNICODE_GREEK_CAPITAL_LETTER_SIGMA ||
                            c == (UV)UNICODE_GREEK_SMALL_LETTER_FINAL_SIGMA)
                            c = (UV)UNICODE_GREEK_SMALL_LETTER_SIGMA;
-                       if ( (((c == c1 || c == c2) && ln == len) ||
-                             ((f == c1 || f == c2) && ln == foldlen) ||
-                             !ibcmp_utf8(s, do_utf8, (I32)(strend - s),
-                                         m, UTF, (I32)ln))
+
+                       if ( (c == c1 || c == c2)
+                            && (ln == len ||
+                                ibcmp_utf8(s, (char **)0, 0,  do_utf8,
+                                           m, (char **)0, ln, UTF))
                             && (norun || regtry(prog, s)) )
                            goto got_it;
+                       else {
+                            uvchr_to_utf8(tmpbuf, c);
+                            f = to_utf8_fold(tmpbuf, foldbuf, &foldlen);
+                            if ( f != c
+                                 && (f == c1 || f == c2)
+                                 && (ln == foldlen ||
+                                     !ibcmp_utf8((char *)foldbuf,
+                                                 (char **)0, foldlen, do_utf8,
+                                                 m,
+                                                 (char **)0, ln,      UTF))
+                                 && (norun || regtry(prog, s)) )
+                                 goto got_it;
+                       }
                        s += len;
                    }
                }
@@ -2309,81 +2338,17 @@ S_regmatch(pTHX_ regnode *prog)
            s = STRING(scan);
            ln = STR_LEN(scan);
 
-           {
+           if (do_utf8 || UTF) {
+             /* Either target or the pattern are utf8. */
                char *l = locinput;
-               char *e = s + ln;
-               U8 tmpbuf[UTF8_MAXLEN_FOLD+1];
-
-               if (do_utf8 != (UTF!=0)) {
-                    /* The target and the pattern have differing utf8ness. */
-                    STRLEN ulen1, ulen2;
-                    UV cs, cl;
-
-                    if (do_utf8) {
-                         /* The target is utf8, the pattern is not utf8. */
-                         while (s < e) {
-                              if (l >= PL_regeol)
-                                   sayNO;
-
-                              cs = to_uni_fold(NATIVE_TO_UNI(*(U8*)s),
-                                               (U8*)s, &ulen1);
-                              cl = utf8_to_uvchr((U8*)l, &ulen2);
-
-                              if (cs != cl) {
-                                   cl = to_uni_fold(cl, (U8*)l, &ulen2);
-                                   if (ulen1 != ulen2 || cs != cl)
-                                        sayNO;
-                              }
-                              l += ulen1;
-                              s ++;
-                         }
-                    }
-                    else {
-                         /* The target is not utf8, the pattern is utf8. */
-                         while (s < e) {
-                              if (l >= PL_regeol)
-                                   sayNO;
-
-                              cs = utf8_to_uvchr((U8*)s, &ulen1);
-
-                              cl = to_uni_fold(NATIVE_TO_UNI(*(U8*)l),
-                                               (U8*)l, &ulen2);
-
-                              if (cs != cl) {
-                                   cs = to_uni_fold(cs, (U8*)s, &ulen1);
-                                   if (ulen1 != ulen2 || cs != cl)
-                                        sayNO;
-                              }
-                              l ++;
-                              s += ulen1;
-                         }
-                    }
-                    locinput = l;
-                    nextchr = UCHARAT(locinput);
-                    break;
-               }
+               char *e = PL_regeol;
 
-               if (do_utf8 && UTF) {
-                    /* Both the target and the pattern are utf8. */
-                    STRLEN ulen;
-                    
-                    while (s < e) {
-                         if (l >= PL_regeol)
-                              sayNO;
-                         if (UTF8SKIP(s) != UTF8SKIP(l) ||
-                             memNE(s, (char*)l, UTF8SKIP(s))) {
-                              to_utf8_fold((U8*)l, tmpbuf, &ulen);
-                              if (UTF8SKIP(s) != ulen ||
-                                  memNE(s, (char*)tmpbuf, ulen))
-                                   sayNO;
-                         }
-                         l += UTF8SKIP(l);
-                         s += UTF8SKIP(s);
-                    }
-                    locinput = l;
-                    nextchr = UCHARAT(locinput);
-                    break;
-               }
+               if (ibcmp_utf8(s, 0,  ln, do_utf8,
+                              l, &e, 0,  UTF))
+                    sayNO;
+               locinput = e;
+               nextchr = UCHARAT(locinput);
+               break;
            }
 
            /* Neither the target and the pattern are utf8. */
@@ -2404,11 +2369,13 @@ S_regmatch(pTHX_ regnode *prog)
            break;
        case ANYOF:
            if (do_utf8) {
-               if (!reginclass(scan, (U8*)locinput, do_utf8))
+               STRLEN inclasslen = PL_regeol - locinput;
+
+               if (!reginclasslen(scan, (U8*)locinput, &inclasslen, do_utf8))
                    sayNO;
                if (locinput >= PL_regeol)
                    sayNO;
-               locinput += PL_utf8skip[nextchr];
+               locinput += inclasslen;
                nextchr = UCHARAT(locinput);
            }
            else {
@@ -4142,10 +4109,11 @@ S_regrepeat_hard(pTHX_ regnode *p, I32 max, I32 *lp)
 */
 
 SV *
-Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** initsvp)
+Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** listsvp, SV **altsvp)
 {
-    SV *sw = NULL;
-    SV *si = NULL;
+    SV *sw  = NULL;
+    SV *si  = NULL;
+    SV *alt = NULL;
 
     if (PL_regdata && PL_regdata->count) {
        U32 n = ARG(node);
@@ -4153,10 +4121,11 @@ Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** initsvp)
        if (PL_regdata->what[n] == 's') {
            SV *rv = (SV*)PL_regdata->data[n];
            AV *av = (AV*)SvRV((SV*)rv);
-           SV **a;
+           SV **a, **b;
        
-           si = *av_fetch(av, 0, FALSE);
-           a  =  av_fetch(av, 1, FALSE);
+           si  = *av_fetch(av, 0, FALSE);
+           a   =  av_fetch(av, 1, FALSE);
+           b   =  av_fetch(av, 2, FALSE);
        
            if (a)
                sw = *a;
@@ -4164,11 +4133,15 @@ Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** initsvp)
                sw = swash_init("utf8", "", si, 1, 0);
                (void)av_store(av, 1, sw);
            }
+           if (b)
+               alt = *b;
        }
     }
        
-    if (initsvp)
-       *initsvp = si;
+    if (listsvp)
+       *listsvp = si;
+    if (altsvp)
+       *altsvp  = alt;
 
     return sw;
 }
@@ -4178,16 +4151,20 @@ Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** initsvp)
  */
 
 STATIC bool
-S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
+S_reginclasslen(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, register bool do_utf8)
 {
     char flags = ANYOF_FLAGS(n);
     bool match = FALSE;
     UV c;
     STRLEN len = 0;
+    STRLEN plen;
 
     c = do_utf8 ? utf8_to_uvchr(p, &len) : *p;
 
+    plen = lenp ? *lenp : UNISKIP(c);
     if (do_utf8 || (flags & ANYOF_UNICODE)) {
+        if (lenp)
+           *lenp = 0;
        if (do_utf8 && !ANYOF_RUNTIME(n)) {
            if (len != (STRLEN)-1 && c < 256 && ANYOF_BITMAP_TEST(n, c))
                match = TRUE;
@@ -4195,24 +4172,46 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
        if (!match && do_utf8 && (flags & ANYOF_UNICODE_ALL) && c >= 256)
            match = TRUE;
        if (!match) {
-           SV *sw = regclass_swash(n, TRUE, 0);
+           AV *av;
+           SV *sw = regclass_swash(n, TRUE, 0, (SV**)&av);
        
            if (sw) {
                if (swash_fetch(sw, p, do_utf8))
                    match = TRUE;
                else if (flags & ANYOF_FOLD) {
-                   STRLEN ulen;
                    U8 tmpbuf[UTF8_MAXLEN_FOLD+1];
+                   STRLEN tmplen;
 
-                   to_utf8_fold(p, tmpbuf, &ulen);
-                   if (swash_fetch(sw, tmpbuf, do_utf8))
-                       match = TRUE;
-                   to_utf8_upper(p, tmpbuf, &ulen);
-                   if (swash_fetch(sw, tmpbuf, do_utf8))
-                       match = TRUE;
+                   if (!match && lenp && av) {
+                       I32 i;
+                     
+                       for (i = 0; i <= av_len(av); i++) {
+                           SV* sv = *av_fetch(av, i, FALSE);
+                           STRLEN len;
+                           char *s = SvPV(sv, len);
+                       
+                           if (len <= plen && memEQ(s, p, len)) {
+                               *lenp = len;
+                               match = TRUE;
+                               break;
+                           }
+                       }
+                   }
+                   if (!match) {
+                       to_utf8_fold(p, tmpbuf, &tmplen);
+                       if (swash_fetch(sw, tmpbuf, do_utf8))
+                           match = TRUE;
+                   }
+                   if (!match) {
+                       to_utf8_upper(p, tmpbuf, &tmplen);
+                       if (swash_fetch(sw, tmpbuf, do_utf8))
+                           match = TRUE;
+                   }
                }
            }
        }
+       if (match && lenp && *lenp == 0)
+           *lenp = UNISKIP(c);
     }
     if (!match && c < 256) {
        if (ANYOF_BITMAP_TEST(n, c))
@@ -4273,6 +4272,12 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
     return (flags & ANYOF_INVERT) ? !match : match;
 }
 
+STATIC bool
+S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8)
+{
+    return S_reginclasslen(aTHX_ n, p, 0, do_utf8);
+}
+
 STATIC U8 *
 S_reghop(pTHX_ U8 *s, I32 off)
 {