SV *dsv = PERL_DEBUG_PAD_ZERO(0);
#endif
+ if (prog->reganch & ROPT_UTF8) {
+ DEBUG_r(PerlIO_printf(Perl_debug_log,
+ "UTF-8 regex...\n"));
+ PL_reg_flags |= RF_utf8;
+ }
+
DEBUG_r({
- char*s = UTF ? sv_uni_display(dsv, sv, 60, 0) : strpos;
- int len = UTF ? strlen(s) : strend - strpos;
+ char *s = PL_reg_match_utf8 ?
+ sv_uni_display(dsv, sv, 60, 0) : strpos;
+ int len = PL_reg_match_utf8 ?
+ strlen(s) : strend - strpos;
if (!PL_colorset)
reginitcolors();
+ if (PL_reg_match_utf8)
+ DEBUG_r(PerlIO_printf(Perl_debug_log,
+ "UTF-8 target...\n"));
PerlIO_printf(Perl_debug_log,
"%sGuessing start of match, REx%s `%s%.60s%s%s' against `%s%.*s%s%s'...\n",
PL_colors[4],PL_colors[5],PL_colors[0],
);
});
- if (prog->reganch & ROPT_UTF8)
- PL_reg_flags |= RF_utf8;
-
if (prog->minlen > CHR_DIST((U8*)strend, (U8*)strpos)) {
DEBUG_r(PerlIO_printf(Perl_debug_log,
"String too short... [re_intuit_start]\n"));
ln = STR_LEN(c);
if (UTF) {
STRLEN ulen1, ulen2;
- U8 tmpbuf1[UTF8_MAXLEN*2+1];
- U8 tmpbuf2[UTF8_MAXLEN*2+1];
+ U8 tmpbuf1[UTF8_MAXLEN_UCLC+1];
+ U8 tmpbuf2[UTF8_MAXLEN_UCLC+1];
to_utf8_lower((U8*)m, tmpbuf1, &ulen1);
to_utf8_upper((U8*)m, tmpbuf2, &ulen2);
c1 = *(U8*)m;
c2 = PL_fold_locale[c1];
do_exactf:
- e = strend - ln;
+ e = do_utf8 ? s + ln - 1 : 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 */
- if (c1 == c2)
+ UV c, f;
+ U8 tmpbuf [UTF8_MAXLEN+1];
+ U8 foldbuf[UTF8_MAXLEN_FOLD+1];
+ STRLEN len, foldlen;
+ char* se;
+
+ if (c1 == c2) {
while (s <= e) {
- if ( utf8_to_uvchr((U8*)s, &len) == c1
- && (ln == 1 ||
- ibcmp_utf8(s, do_utf8, strend - s,
- m, UTF, ln)) )
+ c = utf8_to_uvchr((U8*)s, &len);
+ if ( c == c1
+ && (ln == len ||
+ ((se = e + 1) &&
+ !ibcmp_utf8(s, &se, 0, do_utf8,
+ m, 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,
+ 0, foldlen, do_utf8,
+ m,
+ 0, ln, UTF))
+ && (norun || regtry(prog, s)) )
+ goto got_it;
+ }
s += len;
}
- else
+ }
+ else {
while (s <= e) {
- UV c = utf8_to_uvchr((U8*)s, &len);
+ 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)
- && (ln == 1 ||
- ibcmp_utf8(s, do_utf8, strend - s,
- m, UTF, ln)) )
+ && (ln == len ||
+ ((se = e + 1) &&
+ !ibcmp_utf8(s, &se, 0, do_utf8,
+ m, 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,
+ 0, foldlen, do_utf8,
+ m,
+ 0, ln, UTF))
+ && (norun || regtry(prog, s)) )
+ goto got_it;
+ }
s += len;
}
+ }
}
else {
if (c1 == c2)
s = STRING(scan);
ln = STR_LEN(scan);
if (do_utf8 != (UTF!=0)) {
- /* The target and the pattern have differing "utf8ness". */
+ /* The target and the pattern have differing utf8ness. */
char *l = locinput;
char *e = s + ln;
- STRLEN len;
+ STRLEN ulen;
if (do_utf8) {
/* The target is utf8, the pattern is not utf8. */
if (l >= PL_regeol)
sayNO;
if (NATIVE_TO_UNI(*(U8*)s) !=
- utf8_to_uvchr((U8*)l, &len))
+ utf8_to_uvchr((U8*)l, &ulen))
sayNO;
- l += len;
+ l += ulen;
s ++;
}
}
if (l >= PL_regeol)
sayNO;
if (NATIVE_TO_UNI(*((U8*)l)) !=
- utf8_to_uvchr((U8*)s, &len))
+ utf8_to_uvchr((U8*)s, &ulen))
sayNO;
- s += len;
+ s += ulen;
l ++;
}
}
nextchr = UCHARAT(locinput);
break;
}
- /* The target and the pattern have the same "utf8ness". */
+ /* The target and the pattern have the same utf8ness. */
/* Inline the first character, for speed. */
if (UCHARAT(s) != nextchr)
sayNO;
s = STRING(scan);
ln = STR_LEN(scan);
- if (do_utf8) {
+ if (do_utf8 || UTF) {
+ /* Either target or the pattern are utf8. */
char *l = locinput;
- char *e;
- STRLEN ulen;
- U8 tmpbuf[UTF8_MAXLEN*2+1];
- e = s + ln;
- while (s < e) {
- if (l >= PL_regeol)
- sayNO;
- toLOWER_utf8((U8*)l, tmpbuf, &ulen);
- if (memNE(s, (char*)tmpbuf, ulen))
- sayNO;
- s += UTF8SKIP(s);
- l += ulen;
- }
- locinput = l;
+ char *e = PL_regeol;
+
+ 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. */
+
/* Inline the first character, for speed. */
if (UCHARAT(s) != nextchr &&
UCHARAT(s) != ((OP(scan) == EXACTF)
nextchr = UCHARAT(++locinput);
break;
case CLUMP:
- LOAD_UTF8_CHARCLASS(mark,"~");
- 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, do_utf8))
- locinput += UTF8SKIP(locinput);
- if (locinput > PL_regeol)
+ if (locinput >= PL_regeol)
sayNO;
+ if (do_utf8) {
+ LOAD_UTF8_CHARCLASS(mark,"~");
+ if (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, do_utf8))
+ locinput += UTF8SKIP(locinput);
+ if (locinput > PL_regeol)
+ sayNO;
+ }
+ else
+ locinput++;
nextchr = UCHARAT(locinput);
break;
case REFFL:
*/
if (OP(scan) == REFF) {
STRLEN ulen1, ulen2;
- U8 tmpbuf1[UTF8_MAXLEN*2+1];
- U8 tmpbuf2[UTF8_MAXLEN*2+1];
+ U8 tmpbuf1[UTF8_MAXLEN_UCLC+1];
+ U8 tmpbuf2[UTF8_MAXLEN_UCLC+1];
while (s < e) {
if (l >= PL_regeol)
sayNO;
else { /* UTF */
if (OP(text_node) == EXACTF || OP(text_node) == REFF) {
STRLEN ulen1, ulen2;
- U8 tmpbuf1[UTF8_MAXLEN*2+1];
- U8 tmpbuf2[UTF8_MAXLEN*2+1];
+ U8 tmpbuf1[UTF8_MAXLEN_UCLC+1];
+ U8 tmpbuf2[UTF8_MAXLEN_UCLC+1];
to_utf8_lower((U8*)s, tmpbuf1, &ulen1);
to_utf8_upper((U8*)s, tmpbuf2, &ulen2);
if (swash_fetch(sw, p, do_utf8))
match = TRUE;
else if (flags & ANYOF_FOLD) {
- STRLEN ulen;
- U8 tmpbuf[UTF8_MAXLEN*2+1];
+ U8 foldbuf[UTF8_MAXLEN_FOLD+1];
+ STRLEN foldlen;
- toLOWER_utf8(p, tmpbuf, &ulen);
- if (swash_fetch(sw, tmpbuf, do_utf8))
+ to_utf8_fold(p, foldbuf, &foldlen);
+ if (swash_fetch(sw, foldbuf, do_utf8))
+ match = TRUE;
+ to_utf8_upper(p, foldbuf, &foldlen);
+ if (swash_fetch(sw, foldbuf, do_utf8))
match = TRUE;
}
}