Index: lib/libc/regex/regcomp.c =================================================================== --- lib/libc/regex/regcomp.c +++ lib/libc/regex/regcomp.c @@ -132,7 +132,7 @@ static void p_b_eclass(struct parse *p, cset *cs); static wint_t p_b_symbol(struct parse *p); static wint_t p_b_coll_elem(struct parse *p, wint_t endc); -static wint_t othercase(wint_t ch); +static bool hasothercase(wint_t ch); static void bothcases(struct parse *p, wint_t ch); static void ordinary(struct parse *p, wint_t ch); static void nonnewline(struct parse *p); @@ -1101,19 +1101,22 @@ } /* - - othercase - return the case counterpart of an alphabetic - == static wint_t othercase(wint_t ch); + * Check if alphabetic character has the other case mapping. */ -static wint_t /* if no counterpart, return ch */ -othercase(wint_t ch) +static bool +hasothercase(wint_t ch) { + wint_t other; + assert(iswalpha(ch)); + + other = ch; if (iswupper(ch)) - return(towlower(ch)); + other = towlower(ch); else if (iswlower(ch)) - return(towupper(ch)); - else /* peculiar, but could happen */ - return(ch); + other = towupper(ch); + + return (other != ch); } /* @@ -1131,7 +1134,7 @@ size_t n; mbstate_t mbs; - assert(othercase(ch) != ch); /* p_bracket() would recurse */ + assert(hasothercase(ch)); /* p_bracket() would recurse */ p->next = bracket; memset(&mbs, 0, sizeof(mbs)); n = wcrtomb(bracket, ch, &mbs); @@ -1154,7 +1157,7 @@ { cset *cs; - if ((p->g->cflags®_ICASE) && iswalpha(ch) && othercase(ch) != ch) + if ((p->g->cflags®_ICASE) && iswalpha(ch) && hasothercase(ch)) bothcases(p, ch); else if ((ch & OPDMASK) == ch) EMIT(OCHAR, ch); Index: lib/libc/regex/regex2.h =================================================================== --- lib/libc/regex/regex2.h +++ lib/libc/regex/regex2.h @@ -113,7 +113,7 @@ wint_t max; } crange; typedef struct { - unsigned char bmp[NC / 8]; + unsigned char bmp[NC_MAX / 8]; wctype_t *types; unsigned int ntypes; wint_t *wides; @@ -133,9 +133,14 @@ if (ch < NC) return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^ cs->invert); - for (i = 0; i < cs->nwides; i++) - if (ch == cs->wides[i]) + for (i = 0; i < cs->nwides; i++) { + if (cs->icase) { + if (ch == towlower(cs->wides[i]) || + ch == towupper(cs->wides[i])) + return (!cs->invert); + } else if (ch == cs->wides[i]) return (!cs->invert); + } for (i = 0; i < cs->nranges; i++) if (cs->ranges[i].min <= ch && ch <= cs->ranges[i].max) return (!cs->invert); Index: lib/libc/regex/utils.h =================================================================== --- lib/libc/regex/utils.h +++ lib/libc/regex/utils.h @@ -39,7 +39,9 @@ /* utility definitions */ #define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ #define INFINITY (DUPMAX + 1) -#define NC (CHAR_MAX - CHAR_MIN + 1) +#define NC_MAX (CHAR_MAX - CHAR_MIN + 1) +#define NC ((MB_CUR_MAX == 1) ? \ + (CHAR_MAX - CHAR_MIN + 1) : (CHAR_MAX + 1)) typedef unsigned char uch; /* switch off assertions (if not already off) if no REDEBUG */