git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] grep: use regcomp() for icase search with non-ascii patterns

From
Duy Nguyen <pclouds@gmail.com>
Date
Jul 6, 2015, 23:02 UTC
Message-ID
<CACsJy8BDdxoN3m=FW9sCztz4Egjw7xnxXGZUkWQ3hAK9yXisnA@mail.gmail.com>
In-Reply-To
<559AE0B9.2040704@web.de>
On Tue, Jul 7, 2015 at 3:10 AM, René Scharfe <l.s.r@web.de> wrote:
Show 36 quoted lines
> Am 06.07.2015 um 14:42 schrieb Nguyễn Thái Ngọc Duy:
>>
>> Noticed-by: Plamen Totev <plamen.totev@abv.bg>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>> ---
>>   grep.c | 14 +++++++++++---
>>   1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/grep.c b/grep.c
>> index b58c7c6..48db15a 100644
>> --- a/grep.c
>> +++ b/grep.c
>> @@ -378,7 +378,7 @@ static void free_pcre_regexp(struct grep_pat *p)
>>   }
>>   #endif /* !USE_LIBPCRE */
>>
>> -static int is_fixed(const char *s, size_t len)
>> +static int is_fixed(const char *s, size_t len, int ignore_icase)
>>   {
>>         size_t i;
>>
>> @@ -391,6 +391,13 @@ static int is_fixed(const char *s, size_t len)
>>         for (i = 0; i < len; i++) {
>>                 if (is_regex_special(s[i]))
>>                         return 0;
>> +               /*
>> +                * The builtin substring search can only deal with case
>> +                * insensitivity in ascii range. If there is something
>> outside
>> +                * of that range, fall back to regcomp.
>> +                */
>> +               if (ignore_icase && (unsigned char)s[i] >= 128)
>> +                       return 0;
>
>
> How about "isascii(s[i])"?
Yes, better.
Show 17 quoted lines
>
>>         }
>>
>>         return 1;
>> @@ -398,18 +405,19 @@ static int is_fixed(const char *s, size_t len)
>>
>>   static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
>>   {
>> +       int ignore_icase = opt->regflags & REG_ICASE || p->ignore_case;
>>         int err;
>>
>>         p->word_regexp = opt->word_regexp;
>>         p->ignore_case = opt->ignore_case;
>
>
> Using p->ignore_case before this line, as in initialization of the new
> variable ignore_icase above, changes the meaning.
Oops.
Show 14 quoted lines
>> -       if (opt->fixed || is_fixed(p->pattern, p->patternlen))
>> +       if (opt->fixed || is_fixed(p->pattern, p->patternlen,
>> ignore_icase))
>>                 p->fixed = 1;
>>         else
>>                 p->fixed = 0;
>>
>>         if (p->fixed) {
>> -               if (opt->regflags & REG_ICASE || p->ignore_case)
>> +               if (ignore_case)
>
>
> ignore_icase instead?  ignore_case is for the config variable
> core.ignorecase.  Tricky.

Maybe we can test isascii separately and save the result in has_non_ascii, then we can avoid ignore_(i)case

Show 19 quoted lines
>
>>                         p->kws = kwsalloc(tolower_trans_tbl);
>>                 else
>>                         p->kws = kwsalloc(NULL);
>>
>
> So the optimization before this patch was that if a string was searched for
> without -F then it would be treated as a fixed string anyway unless it
> contained regex special characters.  Searching for fixed strings using the
> kwset functions is faster than using regcomp and regexec, which makes the
> exercise worthwhile.
>
> Your patch disables the optimization if non-ASCII characters are searched
> for because kwset handles case transformations only for ASCII chars.
>
> Another consequence of this limitation is that -Fi (explicit
> case-insensitive fixed-string search) doesn't work properly with non-ASCII
> chars neither.  How can we handle this one?  Fall back to regcomp by
> escaping all special characters?  Or at least warn?

Hehe.. I noticed it too shortly after sending the patch. I was torn between simply documenting the limitation and waiting for the next person to come and fix it, or quoting the regex then passing to regcomp. GNU grep does the quoting in this case, but that code is GPLv3 so we can't simply copy over. It could be a problem if we need to quote a regex in a multibyte charset where ascii is not a subset. But i guess we can just go with utf-8..

> Tests would be nice. :)

Yeah.. but we now rely on system regcomp which may behave differently across platforms. Then we need some locale to be always there. Some platforms (like Gentoo) even allow building glibc without i18n.. So I'm not sure how we know when to test or skip.

-- 
Duy
Previous: René ScharfeNext: Plamen Totev
Message 11 of 53 in “Git grep does not support multi-byte characters (like UTF-8)”
  1. Plamen TotevJul 6, 2015
  2. Duy NguyenJul 6, 2015
  3. Plamen TotevJul 7, 2015
  4. Duy NguyenJul 7, 2015
  5. Junio C HamanoJul 7, 2015
  6. Plamen TotevJul 7, 2015
  7. Duy NguyenJul 8, 2015
  8. Junio C HamanoJul 8, 2015
  9. grep: use regcomp() for icase search with non-ascii patternsNguyễn Thái Ngọc Duy, Jul 6, 2015
  10. René ScharfeJul 6, 2015
  11. Duy NguyenJul 6, 2015
  12. Plamen TotevJul 7, 2015
  13. 0/9 icase match on non-asciiNguyễn Thái Ngọc Duy, Jul 8, 2015
  14. 1/9 grep: allow -F -i combinationNguyễn Thái Ngọc Duy, Jul 8, 2015
  15. 2/9 grep: break down an "if" stmt in preparation for next changesNguyễn Thái Ngọc Duy, Jul 8, 2015
  16. 3/9 grep/icase: avoid kwsset on literal non-ascii stringsNguyễn Thái Ngọc Duy, Jul 8, 2015
  17. 4/9 grep/icase: avoid kwsset when -F is specifiedNguyễn Thái Ngọc Duy, Jul 8, 2015
  18. 5/9 grep/pcre: prepare locale-dependent tables for icase matchingNguyễn Thái Ngọc Duy, Jul 8, 2015
  19. Duy NguyenJul 8, 2015
  20. 6/9 gettext: add is_utf8_locale()Nguyễn Thái Ngọc Duy, Jul 8, 2015
  21. 7/9 grep/pcre: support utf-8Nguyễn Thái Ngọc Duy, Jul 8, 2015
  22. Plamen TotevJul 11, 2015
  23. 8/9 diffcore-pickaxe: "share" regex error handling codeNguyễn Thái Ngọc Duy, Jul 8, 2015
  24. 9/9 diffcore-pickaxe: support case insensitive match on non-asciiNguyễn Thái Ngọc Duy, Jul 8, 2015
  25. Eric SunshineJul 9, 2015
  26. Torsten BögershausenJul 8, 2015
  27. Duy NguyenJul 8, 2015
  28. Junio C HamanoJul 8, 2015
  29. Duy NguyenJul 8, 2015
  30. 0/9 icase match on non-asciiNguyễn Thái Ngọc Duy, Jul 14, 2015
  31. 1/9 grep: allow -F -i combinationNguyễn Thái Ngọc Duy, Jul 14, 2015
  32. 2/9 grep: break down an "if" stmt in preparation for next changesNguyễn Thái Ngọc Duy, Jul 14, 2015
  33. 3/9 grep/icase: avoid kwsset on literal non-ascii stringsNguyễn Thái Ngọc Duy, Jul 14, 2015
  34. 4/9 grep/icase: avoid kwsset when -F is specifiedNguyễn Thái Ngọc Duy, Jul 14, 2015
  35. 5/9 grep/pcre: prepare locale-dependent tables for icase matchingNguyễn Thái Ngọc Duy, Jul 14, 2015
  36. 6/9 gettext: add is_utf8_locale()Nguyễn Thái Ngọc Duy, Jul 14, 2015
  37. 7/9 grep/pcre: support utf-8Nguyễn Thái Ngọc Duy, Jul 14, 2015
  38. 8/9 diffcore-pickaxe: "share" regex error handling codeNguyễn Thái Ngọc Duy, Jul 14, 2015
  39. 9/9 diffcore-pickaxe: support case insensitive match on non-asciiNguyễn Thái Ngọc Duy, Jul 14, 2015
  40. Torsten BögershausenJul 14, 2015
  41. Duy NguyenJul 15, 2015
  42. Torsten BögershausenJul 15, 2015
  43. 00/10 icase match on non-asciiNguyễn Thái Ngọc Duy, Aug 21, 2015
  44. 01/10 grep: allow -F -i combinationNguyễn Thái Ngọc Duy, Aug 21, 2015
  45. 02/10 grep: break down an "if" stmt in preparation for next changesNguyễn Thái Ngọc Duy, Aug 21, 2015
  46. 03/10 test-regex: expose full regcomp() to the command lineNguyễn Thái Ngọc Duy, Aug 21, 2015
  47. 04/10 grep/icase: avoid kwsset on literal non-ascii stringsNguyễn Thái Ngọc Duy, Aug 21, 2015
  48. 05/10 grep/icase: avoid kwsset when -F is specifiedNguyễn Thái Ngọc Duy, Aug 21, 2015
  49. 06/10 grep/pcre: prepare locale-dependent tables for icase matchingNguyễn Thái Ngọc Duy, Aug 21, 2015
  50. 07/10 gettext: add is_utf8_locale()Nguyễn Thái Ngọc Duy, Aug 21, 2015
  51. 08/10 grep/pcre: support utf-8Nguyễn Thái Ngọc Duy, Aug 21, 2015
  52. 09/10 diffcore-pickaxe: "share" regex error handling codeNguyễn Thái Ngọc Duy, Aug 21, 2015
  53. 10/10 diffcore-pickaxe: support case insensitive match on non-asciiNguyễn Thái Ngọc Duy, Aug 21, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.