diff options
author | Yuri Pankov <yuripv@FreeBSD.org> | 2018-11-23 15:49:18 +0000 |
---|---|---|
committer | Yuri Pankov <yuripv@FreeBSD.org> | 2018-11-23 15:49:18 +0000 |
commit | 63cbe8d1d95f97e93929ec66f1138693d08dd9f6 (patch) | |
tree | 46337131835ddb820baaa2741c6ba0c9250d3bcd /lib/libc/regex/engine.c | |
parent | 76b6af67314008e45e0a761f7d4a6f5080796f09 (diff) |
Notes
Diffstat (limited to 'lib/libc/regex/engine.c')
-rw-r--r-- | lib/libc/regex/engine.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/lib/libc/regex/engine.c b/lib/libc/regex/engine.c index a17629d8cb782..a25bfa08ede77 100644 --- a/lib/libc/regex/engine.c +++ b/lib/libc/regex/engine.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); */ #ifdef SNAMES +#define stepback sstepback #define matcher smatcher #define walk swalk #define dissect sdissect @@ -58,6 +59,7 @@ __FBSDID("$FreeBSD$"); #define match smat #endif #ifdef LNAMES +#define stepback lstepback #define matcher lmatcher #define walk lwalk #define dissect ldissect @@ -68,6 +70,7 @@ __FBSDID("$FreeBSD$"); #define match lmat #endif #ifdef MNAMES +#define stepback mstepback #define matcher mmatcher #define walk mwalk #define dissect mdissect @@ -142,6 +145,39 @@ static const char *pchar(int ch); #endif /* + * Given a multibyte string pointed to by start, step back nchar characters + * from current position pointed to by cur. + */ +static const char * +stepback(const char *start, const char *cur, int nchar) +{ + const char *ret; + int wc, mbc; + mbstate_t mbs; + size_t clen; + + if (MB_CUR_MAX == 1) + return ((cur - nchar) > start ? cur - nchar : NULL); + + ret = cur; + for (wc = nchar; wc > 0; wc--) { + for (mbc = 1; mbc <= MB_CUR_MAX; mbc++) { + if ((ret - mbc) < start) + return (NULL); + memset(&mbs, 0, sizeof(mbs)); + clen = mbrtowc(NULL, ret - mbc, mbc, &mbs); + if (clen != (size_t)-1 && clen != (size_t)-2) + break; + } + if (mbc > MB_CUR_MAX) + return (NULL); + ret -= mbc; + } + + return (ret); +} + +/* - matcher - the actual matching engine == static int matcher(struct re_guts *g, const char *string, \ == size_t nmatch, regmatch_t pmatch[], int eflags); @@ -244,8 +280,13 @@ matcher(struct re_guts *g, ZAPSTATE(&m->mbs); /* Adjust start according to moffset, to speed things up */ - if (dp != NULL && g->moffset > -1) - start = ((dp - g->moffset) < start) ? start : dp - g->moffset; + if (dp != NULL && g->moffset > -1) { + const char *nstart; + + nstart = stepback(start, dp, g->moffset); + if (nstart != NULL) + start = nstart; + } SP("mloop", m->st, *start); @@ -1083,6 +1124,7 @@ pchar(int ch) #endif #endif +#undef stepback #undef matcher #undef walk #undef dissect |