X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regexec.c;h=13832311c7482c18e82397e5e75ff38299a5c2be;hb=917211f59b1d5210f3944956e717bae1a2ca7565;hp=203c8e9687230a5e93710ccf439afa19ef83a9f2;hpb=c728cb41064fc29351e896c61d746060cee08d64;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regexec.c b/regexec.c index 203c8e9..1383231 100644 --- a/regexec.c +++ b/regexec.c @@ -67,7 +67,7 @@ * **** Alterations to Henry's code are... **** - **** Copyright (c) 1991-2001, Larry Wall + **** Copyright (c) 1991-2002, Larry Wall **** **** You may distribute under the terms of either the GNU General Public **** License or the Artistic License, as specified in the README file. @@ -111,7 +111,7 @@ #define HOPMAYBEc(pos,off) ((char*)HOPMAYBE(pos,off)) #define HOPBACK(pos, off) ( \ - (UTF && PL_reg_match_utf8) \ + (PL_reg_match_utf8) \ ? reghopmaybe((U8*)pos, -off) \ : (pos - off >= PL_bostr) \ ? (U8*)(pos - off) \ @@ -126,7 +126,7 @@ #define HOP3c(pos,off,lim) ((char*)HOP3(pos,off,lim)) #define HOPMAYBE3c(pos,off,lim) ((char*)HOPMAYBE3(pos,off,lim)) -#define LOAD_UTF8_CHARCLASS(a,b) STMT_START { if (!CAT2(PL_utf8_,a)) (void)CAT2(is_utf8_, a)((U8*)b); } STMT_END +#define LOAD_UTF8_CHARCLASS(a,b) STMT_START { if (!CAT2(PL_utf8_,a)) { ENTER; save_re_context(); (void)CAT2(is_utf8_, a)((U8*)b); LEAVE; } } STMT_END /* for use after a quantifier and before an EXACT-like node -- japhy */ #define JUMPABLE(rn) ( \ @@ -140,13 +140,18 @@ PL_regkind[(U8)OP(rn)] == EXACT || PL_regkind[(U8)OP(rn)] == REF \ ) +/* + Search for mandatory following text node; for lookahead, the text must + follow but for lookbehind (rn->flags != 0) we skip to the next step. +*/ #define FIND_NEXT_IMPT(rn) STMT_START { \ while (JUMPABLE(rn)) \ - if (OP(rn) == SUSPEND || OP(rn) == IFMATCH || \ - PL_regkind[(U8)OP(rn)] == CURLY) \ + if (OP(rn) == SUSPEND || PL_regkind[(U8)OP(rn)] == CURLY) \ rn = NEXTOPER(NEXTOPER(rn)); \ else if (OP(rn) == PLUS) \ rn = NEXTOPER(rn); \ + else if (OP(rn) == IFMATCH) \ + rn = (rn->flags == 0) ? NEXTOPER(NEXTOPER(rn)) : rn + ARG(rn); \ else rn += NEXT_OFF(rn); \ } STMT_END @@ -916,15 +921,22 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta switch (OP(c)) { case ANYOF: while (s < strend) { - if (reginclass(c, (U8*)s, do_utf8)) { + STRLEN skip = do_utf8 ? UTF8SKIP(s) : 1; + + if (reginclass(c, (U8*)s, do_utf8) || + (ANYOF_FOLD_SHARP_S(c, s, strend) && + /* The assignment of 2 is intentional: + * for the sharp s, the skip is 2. */ + (skip = SHARP_S_SKIP) + )) { if (tmp && (norun || regtry(prog, s))) goto got_it; else tmp = doevery; } - else - tmp = 1; - s += do_utf8 ? UTF8SKIP(s) : 1; + else + tmp = 1; + s += skip; } break; case CANY: @@ -947,8 +959,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta 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); + c1 = utf8_to_uvchr(tmpbuf1, 0); + c2 = utf8_to_uvchr(tmpbuf2, 0); } else { c1 = *(U8*)m; @@ -972,9 +984,10 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta * 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). */ + * than just upper and lower: one needs to use + * the so-called folding case for case-insensitive + * matching (called "loose matching" in Unicode). + * ibcmp_utf8() will do just that. */ if (do_utf8) { UV c, f; @@ -1012,12 +1025,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta 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(). */ + * Note that not all the possible combinations + * are handled here: some of them are 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; @@ -1034,7 +1047,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta if ( f != c && (f == c1 || f == c2) && (ln == foldlen || - !ibcmp_utf8((char *)foldbuf, + !ibcmp_utf8((char *) foldbuf, (char **)0, foldlen, do_utf8, m, (char **)0, ln, UTF)) @@ -1554,9 +1567,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * } minlen = prog->minlen; - if (strend - startpos < minlen && - !PL_reg_match_utf8 /* ANYOFs can balloon to EXACTFs */ - ) { + if (strend - startpos < minlen) { DEBUG_r(PerlIO_printf(Perl_debug_log, "String too short [regexec_flags]...\n")); goto phooey; @@ -2110,6 +2121,7 @@ typedef union re_unwind_t { #define sayYES goto yes #define sayNO goto no +#define sayNO_ANYOF goto no_anyof #define sayYES_FINAL goto yes_final #define sayYES_LOUD goto yes_loud #define sayNO_FINAL goto no_final @@ -2324,7 +2336,7 @@ S_regmatch(pTHX_ regnode *prog) if (l >= PL_regeol) sayNO; if (NATIVE_TO_UNI(*(U8*)s) != - utf8_to_uvchr((U8*)l, &ulen)) + utf8_to_uvuni((U8*)l, &ulen)) sayNO; l += ulen; s ++; @@ -2336,7 +2348,7 @@ S_regmatch(pTHX_ regnode *prog) if (l >= PL_regeol) sayNO; if (NATIVE_TO_UNI(*((U8*)l)) != - utf8_to_uvchr((U8*)s, &ulen)) + utf8_to_uvuni((U8*)s, &ulen)) sayNO; s += ulen; l ++; @@ -2369,9 +2381,21 @@ S_regmatch(pTHX_ regnode *prog) char *l = locinput; char *e = PL_regeol; - if (ibcmp_utf8(s, 0, ln, do_utf8, - l, &e, 0, UTF)) - sayNO; + if (ibcmp_utf8(s, 0, ln, UTF, + l, &e, 0, do_utf8)) { + /* One more case for the sharp s: + * pack("U0U*", 0xDF) =~ /ss/i, + * the 0xC3 0x9F are the UTF-8 + * byte sequence for the U+00DF. */ + if (!(do_utf8 && + toLOWER(s[0]) == 's' && + ln >= 2 && + toLOWER(s[1]) == 's' && + (U8)l[0] == 0xC3 && + e - l >= 2 && + (U8)l[1] == 0x9F)) + sayNO; + } locinput = e; nextchr = UCHARAT(locinput); break; @@ -2398,21 +2422,33 @@ S_regmatch(pTHX_ regnode *prog) STRLEN inclasslen = PL_regeol - locinput; if (!reginclasslen(scan, (U8*)locinput, &inclasslen, do_utf8)) - sayNO; + sayNO_ANYOF; if (locinput >= PL_regeol) sayNO; locinput += inclasslen; nextchr = UCHARAT(locinput); + break; } else { if (nextchr < 0) nextchr = UCHARAT(locinput); if (!reginclass(scan, (U8*)locinput, do_utf8)) - sayNO; + sayNO_ANYOF; if (!nextchr && locinput >= PL_regeol) sayNO; nextchr = UCHARAT(++locinput); + break; } + no_anyof: + /* If we might have the case of the German sharp s + * in a casefolding Unicode character class. */ + + if (ANYOF_FOLD_SHARP_S(scan, locinput, PL_regeol)) { + locinput += SHARP_S_SKIP; + nextchr = UCHARAT(locinput); + } + else + sayNO; break; case ALNUML: PL_reg_flags |= RF_tainted; @@ -3074,7 +3110,7 @@ S_regmatch(pTHX_ regnode *prog) if (ckWARN(WARN_REGEXP) && n >= REG_INFTY && !(PL_reg_flags & RF_warned)) { PL_reg_flags |= RF_warned; - Perl_warner(aTHX_ WARN_REGEXP, "%s limit (%d) exceeded", + Perl_warner(aTHX_ packWARN(WARN_REGEXP), "%s limit (%d) exceeded", "Complex regular subexpression recursion", REG_INFTY - 1); } @@ -3126,7 +3162,7 @@ S_regmatch(pTHX_ regnode *prog) if (ckWARN(WARN_REGEXP) && n >= REG_INFTY && !(PL_reg_flags & RF_warned)) { PL_reg_flags |= RF_warned; - Perl_warner(aTHX_ WARN_REGEXP, "%s limit (%d) exceeded", + Perl_warner(aTHX_ packWARN(WARN_REGEXP), "%s limit (%d) exceeded", "Complex regular subexpression recursion", REG_INFTY - 1); } @@ -3586,7 +3622,9 @@ S_regmatch(pTHX_ regnode *prog) n = regrepeat(scan, n); locinput = PL_reginput; if (ln < n && PL_regkind[(U8)OP(next)] == EOL && - (!PL_multiline || OP(next) == SEOL || OP(next) == EOS)) { + ((!PL_multiline && OP(next) != MEOL) || + OP(next) == SEOL || OP(next) == EOS)) + { ln = n; /* why back off? */ /* ...because $ and \Z can match before *and* after newline at the end. Consider "\n\n" =~ /\n+\Z\n/. @@ -3877,7 +3915,15 @@ S_regrepeat(pTHX_ regnode *p, I32 max) } break; case SANY: - scan = loceol; + if (do_utf8) { + loceol = PL_regeol; + while (scan < loceol && hardcount < max) { + scan += UTF8SKIP(scan); + hardcount++; + } + } + else + scan = loceol; break; case CANY: scan = loceol; @@ -4176,7 +4222,13 @@ Perl_regclass_swash(pTHX_ register regnode* node, bool doinit, SV** listsvp, SV } /* - - reginclass - determine if a character falls into a character class + - reginclasslen - determine if a character falls into a character class + + The n is the ANYOF regnode, the p is the target string, lenp + is pointer to the maximum length of how far to go in the p + (if the lenp is zero, UTF8SKIP(p) is used), + do_utf8 tells whether the target string is in UTF-8. + */ STATIC bool @@ -4208,9 +4260,6 @@ S_reginclasslen(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, registe if (swash_fetch(sw, p, do_utf8)) match = TRUE; else if (flags & ANYOF_FOLD) { - U8 tmpbuf[UTF8_MAXLEN_FOLD+1]; - STRLEN tmplen; - if (!match && lenp && av) { I32 i; @@ -4219,7 +4268,7 @@ S_reginclasslen(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, registe STRLEN len; char *s = SvPV(sv, len); - if (len <= plen && memEQ(s, p, len)) { + if (len <= plen && memEQ(s, (char*)p, len)) { *lenp = len; match = TRUE; break; @@ -4227,15 +4276,13 @@ S_reginclasslen(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, registe } } if (!match) { + U8 tmpbuf[UTF8_MAXLEN_FOLD+1]; + STRLEN tmplen; + 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; - } } } } @@ -4301,6 +4348,14 @@ S_reginclasslen(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, registe return (flags & ANYOF_INVERT) ? !match : match; } +/* + - reginclass - determine if a character falls into a character class + + The n is the ANYOF regnode, the p is the target string, do_utf8 tells + whether the target string is in UTF-8. + + */ + STATIC bool S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8) {