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) {
- STRLEN len;
- /* 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 */
+ UV c, f;
+ U8 tmpbuf [UTF8_MAXLEN+1];
+ U8 foldbuf[UTF8_MAXLEN_FOLD+1];
+ STRLEN len, foldlen;
+
if (c1 == c2) {
while (s <= e) {
- if ( utf8_to_uvchr((U8*)s, &len) == c1
+ c = utf8_to_uvchr((U8*)s, &len);
+ if ( c == c1
&& (ln == len ||
- ibcmp_utf8(s, do_utf8, (I32)(strend - s),
- m, UTF, (I32)ln))
+ 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) {
- U8 tmpbuf [UTF8_MAXLEN+1];
- U8 foldbuf[UTF8_MAXLEN_FOLD+1];
- STRLEN foldlen;
- UV c = utf8_to_uvchr((U8*)s, &len);
- UV f;
-
- uvchr_to_utf8(tmpbuf, c);
- to_utf8_fold(tmpbuf, foldbuf, &foldlen);
- f = utf8_to_uvchr(foldbuf, 0);
-
+ c = utf8_to_uvchr((U8*)s, &len);
+
+ /* 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 || f == c1 || f == c2)
- && 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;
}
}
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. */
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 {
*/
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);
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;
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;
}
*/
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;
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))
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)
{