grep: remove regflags from the public grep_opt API

Refactor calls to the grep machinery to always pass opt.ignore_case &
opt.extended_regexp_option instead of setting the equivalent regflags
bits.

The bug fixed when making -i work with -P in commit 9e3cbc59d5 ("log:
make --regexp-ignore-case work with --perl-regexp", 2017-05-20) was
really just plastering over the code smell which this change fixes.

The reason for adding the extensive commentary here is that I
discovered some subtle complexity in implementing this that really
should be called out explicitly to future readers.

Before this change we'd rely on the difference between
`extended_regexp_option` and `regflags` to serve as a membrane between
our preliminary parsing of grep.extendedRegexp and grep.patternType,
and what we decided to do internally.

Now that those two are the same thing, it's necessary to unset
`extended_regexp_option` just before we commit in cases where both of
those config variables are set. See 84befcd0a4 ("grep: add a
grep.patternType configuration setting", 2012-08-03) for the code and
documentation related to that.

The explanation of why the if/else branches in
grep_commit_pattern_type() are ordered the way they are exists in that
commit message, but I think it's worth calling this subtlety out
explicitly with a comment for future readers.

Even though grep_commit_pattern_type() is the only caller of
grep_set_pattern_type_option() it's simpler to reset the
extended_regexp_option flag in the latter, since 2/3 branches in the
former would otherwise need to reset it, this way we can do it in one
place.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ævar Arnfjörð Bjarmason 2017-06-29 22:22:21 +00:00 committed by Junio C Hamano
parent b07ed4e532
commit 07a3d41173
4 changed files with 34 additions and 14 deletions

View File

@ -1169,8 +1169,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (!opt.pattern_list) if (!opt.pattern_list)
die(_("no pattern given.")); die(_("no pattern given."));
if (!opt.fixed && opt.ignore_case)
opt.regflags |= REG_ICASE;
/* /*
* We have to find "--" in a separate pass, because its presence * We have to find "--" in a separate pass, because its presence

43
grep.c
View File

@ -35,7 +35,6 @@ void init_grep_defaults(void)
memset(opt, 0, sizeof(*opt)); memset(opt, 0, sizeof(*opt));
opt->relative = 1; opt->relative = 1;
opt->pathname = 1; opt->pathname = 1;
opt->regflags = REG_NEWLINE;
opt->max_depth = -1; opt->max_depth = -1;
opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED; opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;
color_set(opt->color_context, ""); color_set(opt->color_context, "");
@ -153,7 +152,6 @@ void grep_init(struct grep_opt *opt, const char *prefix)
opt->linenum = def->linenum; opt->linenum = def->linenum;
opt->max_depth = def->max_depth; opt->max_depth = def->max_depth;
opt->pathname = def->pathname; opt->pathname = def->pathname;
opt->regflags = def->regflags;
opt->relative = def->relative; opt->relative = def->relative;
opt->output = def->output; opt->output = def->output;
@ -169,6 +167,24 @@ void grep_init(struct grep_opt *opt, const char *prefix)
static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt) static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
{ {
/*
* When committing to the pattern type by setting the relevant
* fields in grep_opt it's generally not necessary to zero out
* the fields we're not choosing, since they won't have been
* set by anything. The extended_regexp_option field is the
* only exception to this.
*
* This is because in the process of parsing grep.patternType
* & grep.extendedRegexp we set opt->pattern_type_option and
* opt->extended_regexp_option, respectively. We then
* internally use opt->extended_regexp_option to see if we're
* compiling an ERE. It must be unset if that's not actually
* the case.
*/
if (pattern_type != GREP_PATTERN_TYPE_ERE &&
opt->extended_regexp_option)
opt->extended_regexp_option = 0;
switch (pattern_type) { switch (pattern_type) {
case GREP_PATTERN_TYPE_UNSPECIFIED: case GREP_PATTERN_TYPE_UNSPECIFIED:
/* fall through */ /* fall through */
@ -177,7 +193,7 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
break; break;
case GREP_PATTERN_TYPE_ERE: case GREP_PATTERN_TYPE_ERE:
opt->regflags |= REG_EXTENDED; opt->extended_regexp_option = 1;
break; break;
case GREP_PATTERN_TYPE_FIXED: case GREP_PATTERN_TYPE_FIXED:
@ -207,6 +223,11 @@ void grep_commit_pattern_type(enum grep_pattern_type pattern_type, struct grep_o
else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED) else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED)
grep_set_pattern_type_option(opt->pattern_type_option, opt); grep_set_pattern_type_option(opt->pattern_type_option, opt);
else if (opt->extended_regexp_option) else if (opt->extended_regexp_option)
/*
* This branch *must* happen after setting from the
* opt->pattern_type_option above, we don't want
* grep.extendedRegexp to override grep.patternType!
*/
grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt); grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt);
} }
@ -572,7 +593,7 @@ static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
{ {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int err; int err;
int regflags = opt->regflags; int regflags = REG_NEWLINE;
basic_regex_quote_buf(&sb, p->pattern); basic_regex_quote_buf(&sb, p->pattern);
if (opt->ignore_case) if (opt->ignore_case)
@ -591,12 +612,12 @@ static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{ {
int icase, ascii_only; int ascii_only;
int err; int err;
int regflags = REG_NEWLINE;
p->word_regexp = opt->word_regexp; p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case; p->ignore_case = opt->ignore_case;
icase = opt->regflags & REG_ICASE || p->ignore_case;
ascii_only = !has_non_ascii(p->pattern); ascii_only = !has_non_ascii(p->pattern);
/* /*
@ -614,10 +635,10 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
if (opt->fixed || if (opt->fixed ||
has_null(p->pattern, p->patternlen) || has_null(p->pattern, p->patternlen) ||
is_fixed(p->pattern, p->patternlen)) is_fixed(p->pattern, p->patternlen))
p->fixed = !icase || ascii_only; p->fixed = !p->ignore_case || ascii_only;
if (p->fixed) { if (p->fixed) {
p->kws = kwsalloc(icase ? tolower_trans_tbl : NULL); p->kws = kwsalloc(p->ignore_case ? tolower_trans_tbl : NULL);
kwsincr(p->kws, p->pattern, p->patternlen); kwsincr(p->kws, p->pattern, p->patternlen);
kwsprep(p->kws); kwsprep(p->kws);
return; return;
@ -641,7 +662,11 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
return; return;
} }
err = regcomp(&p->regexp, p->pattern, opt->regflags); if (p->ignore_case)
regflags |= REG_ICASE;
if (opt->extended_regexp_option)
regflags |= REG_EXTENDED;
err = regcomp(&p->regexp, p->pattern, regflags);
if (err) { if (err) {
char errbuf[1024]; char errbuf[1024];
regerror(err, &p->regexp, errbuf, 1024); regerror(err, &p->regexp, errbuf, 1024);

1
grep.h
View File

@ -162,7 +162,6 @@ struct grep_opt {
char color_match_selected[COLOR_MAXLEN]; char color_match_selected[COLOR_MAXLEN];
char color_selected[COLOR_MAXLEN]; char color_selected[COLOR_MAXLEN];
char color_sep[COLOR_MAXLEN]; char color_sep[COLOR_MAXLEN];
int regflags;
unsigned pre_context; unsigned pre_context;
unsigned post_context; unsigned post_context;
unsigned last_shown; unsigned last_shown;

View File

@ -1362,7 +1362,6 @@ void init_revisions(struct rev_info *revs, const char *prefix)
init_grep_defaults(); init_grep_defaults();
grep_init(&revs->grep_filter, prefix); grep_init(&revs->grep_filter, prefix);
revs->grep_filter.status_only = 1; revs->grep_filter.status_only = 1;
revs->grep_filter.regflags = REG_NEWLINE;
diff_setup(&revs->diffopt); diff_setup(&revs->diffopt);
if (prefix && !revs->diffopt.prefix) { if (prefix && !revs->diffopt.prefix) {
@ -2022,7 +2021,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE; revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE;
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
revs->grep_filter.ignore_case = 1; revs->grep_filter.ignore_case = 1;
revs->grep_filter.regflags |= REG_ICASE;
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE); DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED; revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;