#define LOAD_UTF8_CHARCLASS(a,b) STMT_START { if (!CAT2(PL_utf8_,a)) (void)CAT2(is_utf8_, a)((U8*)b); } STMT_END
+/* for use after a quantifier and before an EXACT-like node -- japhy */
+#define JUMPABLE(rn) ( \
+ OP(rn) == OPEN || OP(rn) == CLOSE || OP(rn) == EVAL || \
+ OP(rn) == SUSPEND || OP(rn) == IFMATCH \
+)
+
+#define NEAR_EXACT(rn) (PL_regkind[(U8)OP(rn)] == EXACT || JUMPABLE(rn))
+
+#define NEXT_IMPT(rn) STMT_START { \
+ while (JUMPABLE(rn)) \
+ if (OP(rn) == SUSPEND || OP(rn) == IFMATCH) \
+ rn = NEXTOPER(NEXTOPER(rn)); \
+ else rn += NEXT_OFF(rn); \
+} STMT_END
+
static void restore_pos(pTHX_ void *arg);
STATIC CHECKPOINT
m = STRING(c);
ln = STR_LEN(c);
if (UTF) {
- c1 = to_utf8_lower((U8*)m);
- c2 = to_utf8_upper((U8*)m);
+ STRLEN ulen1, ulen2;
+ U8 tmpbuf1[UTF8_MAXLEN*2+1];
+ U8 tmpbuf2[UTF8_MAXLEN*2+1];
+
+ to_utf8_lower((U8*)m, tmpbuf1, &ulen1);
+ to_utf8_upper((U8*)m, tmpbuf2, &ulen2);
+
+ c1 = utf8_to_uvuni(tmpbuf1, 0);
+ c2 = utf8_to_uvuni(tmpbuf2, 0);
}
else {
c1 = *(U8*)m;
if (do_utf8) {
char *l = locinput;
char *e;
+ STRLEN ulen;
+ U8 tmpbuf[UTF8_MAXLEN*2+1];
e = s + ln;
- c1 = OP(scan) == EXACTF;
while (s < e) {
- if (l >= PL_regeol) {
+ if (l >= PL_regeol)
sayNO;
- }
- if ((UTF ? utf8n_to_uvchr((U8*)s, e - s, 0, 0) : *((U8*)s)) !=
- (c1 ? toLOWER_utf8((U8*)l) : toLOWER_LC_utf8((U8*)l)))
- sayNO;
- s += UTF ? UTF8SKIP(s) : 1;
- l += UTF8SKIP(l);
+ toLOWER_utf8((U8*)l, tmpbuf, &ulen);
+ if (memNE(s, tmpbuf, ulen))
+ sayNO;
+ s += UTF8SKIP(s);
+ l += ulen;
}
locinput = l;
nextchr = UCHARAT(locinput);
* have to map both upper and title case to lower case.
*/
if (OP(scan) == REFF) {
+ STRLEN ulen1, ulen2;
+ U8 tmpbuf1[UTF8_MAXLEN*2+1];
+ U8 tmpbuf2[UTF8_MAXLEN*2+1];
while (s < e) {
if (l >= PL_regeol)
sayNO;
- if (toLOWER_utf8((U8*)s) != toLOWER_utf8((U8*)l))
+ toLOWER_utf8((U8*)s, tmpbuf1, &ulen1);
+ toLOWER_utf8((U8*)l, tmpbuf2, &ulen2);
+ if (ulen1 != ulen2 || memNE(tmpbuf1, tmpbuf2, ulen1))
sayNO;
- s += UTF8SKIP(s);
- l += UTF8SKIP(l);
- }
- }
- else {
- while (s < e) {
- if (l >= PL_regeol)
- sayNO;
- if (toLOWER_LC_utf8((U8*)s) != toLOWER_LC_utf8((U8*)l))
- sayNO;
- s += UTF8SKIP(s);
- l += UTF8SKIP(l);
+ s += ulen1;
+ l += ulen2;
}
}
locinput = l;
PL_curpad = AvARRAY((AV*)PL_regdata->data[n + 2]);
PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
- CALLRUNOPS(aTHX); /* Scalar context. */
- SPAGAIN;
- ret = POPs;
- PUTBACK;
-
+ {
+ SV **before = SP;
+ CALLRUNOPS(aTHX); /* Scalar context. */
+ SPAGAIN;
+ if (SP == before)
+ ret = Nullsv; /* protect against empty (?{}) blocks. */
+ else {
+ ret = POPs;
+ PUTBACK;
+ }
+ }
+
PL_op = oop;
PL_curpad = ocurpad;
PL_curcop = ocurcop;
if (ln && l == 0)
n = ln; /* don't backtrack */
locinput = PL_reginput;
- if (PL_regkind[(U8)OP(next)] == EXACT) {
- c1 = (U8)*STRING(next);
- if (OP(next) == EXACTF)
- c2 = PL_fold[c1];
- else if (OP(next) == EXACTFL)
- c2 = PL_fold_locale[c1];
- else
- c2 = c1;
+ if (NEAR_EXACT(next)) {
+ regnode *text_node = next;
+
+ if (PL_regkind[(U8)OP(next)] != EXACT)
+ NEXT_IMPT(text_node);
+
+ if (PL_regkind[(U8)OP(text_node)] != EXACT) {
+ c1 = c2 = -1000;
+ }
+ else {
+ c1 = (U8)*STRING(text_node);
+ if (OP(next) == EXACTF)
+ c2 = PL_fold[c1];
+ else if (OP(text_node) == EXACTFL)
+ c2 = PL_fold_locale[c1];
+ else
+ c2 = c1;
+ }
}
else
c1 = c2 = -1000;
(IV) n, (IV)l)
);
if (n >= ln) {
- if (PL_regkind[(U8)OP(next)] == EXACT) {
- c1 = (U8)*STRING(next);
- if (OP(next) == EXACTF)
- c2 = PL_fold[c1];
- else if (OP(next) == EXACTFL)
- c2 = PL_fold_locale[c1];
- else
- c2 = c1;
+ if (NEAR_EXACT(next)) {
+ regnode *text_node = next;
+
+ if (PL_regkind[(U8)OP(next)] != EXACT)
+ NEXT_IMPT(text_node);
+
+ if (PL_regkind[(U8)OP(text_node)] != EXACT) {
+ c1 = c2 = -1000;
+ }
+ else {
+ c1 = (U8)*STRING(text_node);
+ if (OP(text_node) == EXACTF)
+ c2 = PL_fold[c1];
+ else if (OP(text_node) == EXACTFL)
+ c2 = PL_fold_locale[c1];
+ else
+ c2 = c1;
+ }
}
else
c1 = c2 = -1000;
* Lookahead to avoid useless match attempts
* when we know what character comes next.
*/
- if (PL_regkind[(U8)OP(next)] == EXACT) {
- U8 *s = (U8*)STRING(next);
- if (!UTF) {
- c2 = c1 = *s;
- if (OP(next) == EXACTF)
- c2 = PL_fold[c1];
- else if (OP(next) == EXACTFL)
- c2 = PL_fold_locale[c1];
- }
- else { /* UTF */
- if (OP(next) == EXACTF) {
- c1 = to_utf8_lower(s);
- c2 = to_utf8_upper(s);
+
+ /*
+ * Used to only do .*x and .*?x, but now it allows
+ * for )'s, ('s and (?{ ... })'s to be in the way
+ * of the quantifier and the EXACT-like node. -- japhy
+ */
+
+ if (NEAR_EXACT(next)) {
+ U8 *s;
+ regnode *text_node = next;
+
+ if (PL_regkind[(U8)OP(next)] != EXACT)
+ NEXT_IMPT(text_node);
+
+ if (PL_regkind[(U8)OP(text_node)] != EXACT) {
+ c1 = c2 = -1000;
+ }
+ else {
+ s = (U8*)STRING(text_node);
+
+ if (!UTF) {
+ c2 = c1 = *s;
+ if (OP(text_node) == EXACTF)
+ c2 = PL_fold[c1];
+ else if (OP(text_node) == EXACTFL)
+ c2 = PL_fold_locale[c1];
}
- else {
- c2 = c1 = utf8_to_uvchr(s, NULL);
+ else { /* UTF */
+ if (OP(text_node) == EXACTF) {
+ STRLEN ulen1, ulen2;
+ U8 tmpbuf1[UTF8_MAXLEN*2+1];
+ U8 tmpbuf2[UTF8_MAXLEN*2+1];
+
+ to_utf8_lower((U8*)s, tmpbuf1, &ulen1);
+ to_utf8_upper((U8*)s, tmpbuf2, &ulen2);
+
+ c1 = utf8_to_uvuni(tmpbuf1, 0);
+ c2 = utf8_to_uvuni(tmpbuf2, 0);
+ }
+ else {
+ c2 = c1 = utf8_to_uvchr(s, NULL);
+ }
}
}
}
/* Find place 'next' could work */
if (!do_utf8) {
if (c1 == c2) {
- while (locinput <= e && *locinput != c1)
+ while (locinput <= e &&
+ UCHARAT(locinput) != c1)
locinput++;
} else {
while (locinput <= e
- && *locinput != c1
- && *locinput != c2)
+ && UCHARAT(locinput) != c1
+ && UCHARAT(locinput) != c2)
locinput++;
}
count = locinput - old;
if (swash_fetch(sw, p, do_utf8))
match = TRUE;
else if (flags & ANYOF_FOLD) {
- U8 tmpbuf[UTF8_MAXLEN+1];
-
- if (flags & ANYOF_LOCALE) {
- PL_reg_flags |= RF_tainted;
- uvchr_to_utf8(tmpbuf, toLOWER_LC_utf8(p));
- }
- else
- uvchr_to_utf8(tmpbuf, toLOWER_utf8(p));
+ STRLEN ulen;
+ U8 tmpbuf[UTF8_MAXLEN*2+1];
+
+ toLOWER_utf8(p, tmpbuf, &ulen);
if (swash_fetch(sw, tmpbuf, do_utf8))
match = TRUE;
}