/* Doesn't do an assert to verify that is correct */
#define LOAD_UTF8_CHARCLASS_NO_CHECK(class) STMT_START { \
if (!CAT2(PL_utf8_,class)) { \
- bool throw_away __attribute__unused__; \
+ bool throw_away PERL_UNUSED_DECL; \
ENTER; save_re_context(); \
throw_away = CAT2(is_utf8_,class)((const U8*)" "); \
LEAVE; } } STMT_END
uscan += len; \
len=0; \
} else { \
- uvc = utf8n_to_uvuni( (U8*)uc, UTF8_MAXLEN, &len, uniflags ); \
- uvc = to_uni_fold( uvc, foldbuf, &foldlen ); \
+ uvc = to_utf8_fold( (U8 *) uc, foldbuf, &foldlen ); \
+ len = UTF8SKIP(uc); \
foldlen -= UNISKIP( uvc ); \
uscan = foldbuf + UNISKIP( uvc ); \
} \
folder = foldEQ_latin1; /* /a, except the sharp s one which */
goto do_exactf_non_utf8; /* isn't dealt with by these */
- case EXACTFU:
- if (UTF_PATTERN || utf8_target) {
- utf8_fold_flags = 0;
- goto do_exactf_utf8;
- }
-
- /* Any 'ss' in the pattern should have been replaced by regcomp,
- * so we don't have to worry here about this single special case
- * in the Latin1 range */
- fold_array = PL_fold_latin1;
- folder = foldEQ_latin1;
- goto do_exactf_non_utf8;
-
case EXACTF:
if (UTF_PATTERN || utf8_target) {
- utf8_fold_flags = 0;
+
+ /* regcomp.c already folded this if pattern is in UTF-8 */
+ utf8_fold_flags = (UTF_PATTERN) ? FOLDEQ_S2_ALREADY_FOLDED : 0;
goto do_exactf_utf8;
}
fold_array = PL_fold;
}
fold_array = PL_fold_locale;
folder = foldEQ_locale;
+ goto do_exactf_non_utf8;
+
+ case EXACTFU:
+ if (UTF_PATTERN || utf8_target) {
+ utf8_fold_flags = (UTF_PATTERN) ? FOLDEQ_S2_ALREADY_FOLDED : 0;
+ goto do_exactf_utf8;
+ }
+
+ /* Any 'ss' in the pattern should have been replaced by regcomp,
+ * so we don't have to worry here about this single special case
+ * in the Latin1 range */
+ fold_array = PL_fold_latin1;
+ folder = foldEQ_latin1;
/* FALL THROUGH */
pat_string = STRING(c);
ln = STR_LEN(c); /* length to match in octets/bytes */
+ /* We know that we have to match at least 'ln' bytes (which is the
+ * same as characters, since not utf8). If we have to match 3
+ * characters, and there are only 2 availabe, we know without
+ * trying that it will fail; so don't start a match past the
+ * required minimum number from the far end */
e = HOP3c(strend, -((I32)ln), s);
if (!reginfo && e < s) {
break;
do_exactf_utf8:
+ {
+ unsigned expansion;
+
/* If one of the operands is in utf8, we can't use the simpler
* folding above, due to the fact that many different characters
? utf8_length((U8 *) pat_string, (U8 *) pat_end)
: ln;
+ /* We have 'lnc' characters to match in the pattern, but because of
+ * multi-character folding, each character in the target can match
+ * up to 3 characters (Unicode guarantees it will never exceed
+ * this) if it is utf8-encoded; and up to 2 if not (based on the
+ * fact that the Latin 1 folds are already determined, and the
+ * only multi-char fold in that range is the sharp-s folding to
+ * 'ss'. Thus, a pattern character can match as little as 1/3 of a
+ * string character. Adjust lnc accordingly, rounding up, so that
+ * if we need to match at least 4+1/3 chars, that really is 5. */
+ expansion = (utf8_target) ? UTF8_MAX_FOLD_CHAR_EXPAND : 2;
+ lnc = (lnc + expansion - 1) / expansion;
+
+ /* As in the non-UTF8 case, if we have to match 3 characters, and
+ * only 2 are left, it's guaranteed to fail, so don't start a
+ * match that would require us to go beyond the end of the string
+ */
e = HOP3c(strend, -((I32)lnc), s);
if (!reginfo && e < s) {
e = s; /* Due to minlen logic of intuit() */
}
+ /* XXX Note that we could recalculate e to stop the loop earlier,
+ * as the worst case expansion above will rarely be met, and as we
+ * go along we would usually find that e moves further to the left.
+ * This would happen only after we reached the point in the loop
+ * where if there were no expansion we should fail. Unclear if
+ * worth the expense */
+
while (s <= e) {
char *my_strend= (char *)strend;
if (foldEQ_utf8_flags(s, &my_strend, 0, utf8_target,
{
goto got_it;
}
- s += UTF8SKIP(s);
+ s += (utf8_target) ? UTF8SKIP(s) : 1;
}
break;
+ }
case BOUNDL:
PL_reg_flags |= RF_tainted;
FBC_BOUND(isALNUM_LC,
case EXACTFU:
folder = foldEQ_latin1;
fold_array = PL_fold_latin1;
- fold_utf8_flags = 0;
+ fold_utf8_flags = (UTF_PATTERN) ? FOLDEQ_S1_ALREADY_FOLDED : 0;
goto do_exactf;
case EXACTFA:
case EXACTF:
folder = foldEQ;
fold_array = PL_fold;
- fold_utf8_flags = 0;
+ fold_utf8_flags = (UTF_PATTERN) ? FOLDEQ_S1_ALREADY_FOLDED : 0;
do_exactf:
s = STRING(scan);
/* Here, the string is utf8, and the pattern char is different
* in utf8 than not, so can't compare them directly. Outside the
- * loop, find find the two utf8 bytes that represent c, and then
+ * loop, find the two utf8 bytes that represent c, and then
* look for those in sequence in the utf8 string */
U8 high = UTF8_TWO_BYTE_HI(c);
U8 low = UTF8_TWO_BYTE_LO(c);
case EXACTF:
case EXACTFU:
- utf8_flags = 0;
+ utf8_flags = (UTF_PATTERN) ? FOLDEQ_S2_ALREADY_FOLDED : 0;
/* The comments for the EXACT case above apply as well to these fold
* ones */
STATIC U8 *
S_reghop3(U8 *s, I32 off, const U8* lim)
{
+ /* return the position 'off' UTF-8 characters away from 's', forward if
+ * 'off' >= 0, backwards if negative. But don't go outside of position
+ * 'lim', which better be < s if off < 0 */
+
dVAR;
PERL_ARGS_ASSERT_REGHOP3;