grep: refactor next_match() and match_one_pattern() for external use

These changes are made in preparation of, the colorization support for the "git log" subcommands that, rely on regex functionality (i.e. "--author", "--committer" and "--grep"). These changes are necessary primarily because match_one_pattern() expects header lines to be prefixed, however, in pretty, the prefixes are stripped from the lines because the name-email pairs need to go through additional parsing, before they can be printed and because next_match() doesn't handle the case of "ctx == GREP_CONTEXT_HEAD" at all. So, teach next_match() how to handle the new case and move match_one_pattern()'s core logic to headerless_match_one_pattern() while preserving match_one_pattern()'s uses that depend on the additional processing. Signed-off-by: Hamza Mahfooz <someguy@effective-light.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Hamza Mahfooz committed Sep 29, 2021 at 07:57 UTC 3f566c4e695a6df8237c34b7c1f34f0832b7e575
2 files changed +58 -30
grep.c
+49 -30
@@ -944,10 +944,10 @@ static struct {
944 { "reflog ", 7 },
945 };
946
947 -static int match_one_pattern(struct grep_pat *p,
948 - const char *bol, const char *eol,
949 - enum grep_context ctx,
950 - regmatch_t *pmatch, int eflags)
947 +static int headerless_match_one_pattern(struct grep_pat *p,
948 + const char *bol, const char *eol,
949 + enum grep_context ctx,
950 + regmatch_t *pmatch, int eflags)
951 {
952 int hit = 0;
953 const char *start = bol;
@@ -956,25 +956,6 @@ static int match_one_pattern(struct grep_pat *p,
956 ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
957 return 0;
958
959 - if (p->token == GREP_PATTERN_HEAD) {
960 - const char *field;
961 - size_t len;
962 - assert(p->field < ARRAY_SIZE(header_field));
963 - field = header_field[p->field].field;
964 - len = header_field[p->field].len;
965 - if (strncmp(bol, field, len))
966 - return 0;
967 - bol += len;
968 - switch (p->field) {
969 - case GREP_HEADER_AUTHOR:
970 - case GREP_HEADER_COMMITTER:
971 - strip_timestamp(bol, &eol);
972 - break;
973 - default:
974 - break;
975 - }
976 - }
977 -
959 again:
960 hit = patmatch(p, bol, eol, pmatch, eflags);
961
@@ -1025,6 +1006,36 @@ static int match_one_pattern(struct grep_pat *p,
1006 return hit;
1007 }
1008
1009 +static int match_one_pattern(struct grep_pat *p,
1010 + const char *bol, const char *eol,
1011 + enum grep_context ctx, regmatch_t *pmatch,
1012 + int eflags)
1013 +{
1014 + const char *field;
1015 + size_t len;
1016 +
1017 + if (p->token == GREP_PATTERN_HEAD) {
1018 + assert(p->field < ARRAY_SIZE(header_field));
1019 + field = header_field[p->field].field;
1020 + len = header_field[p->field].len;
1021 + if (strncmp(bol, field, len))
1022 + return 0;
1023 + bol += len;
1024 +
1025 + switch (p->field) {
1026 + case GREP_HEADER_AUTHOR:
1027 + case GREP_HEADER_COMMITTER:
1028 + strip_timestamp(bol, &eol);
1029 + break;
1030 + default:
1031 + break;
1032 + }
1033 + }
1034 +
1035 + return headerless_match_one_pattern(p, bol, eol, ctx, pmatch, eflags);
1036 +}
1037 +
1038 +
1039 static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x,
1040 const char *bol, const char *eol,
1041 enum grep_context ctx, ssize_t *col,
@@ -1143,7 +1154,7 @@ static int match_next_pattern(struct grep_pat *p,
1154 {
1155 regmatch_t match;
1156
1146 - if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
1157 + if (!headerless_match_one_pattern(p, bol, eol, ctx, &match, eflags))
1158 return 0;
1159 if (match.rm_so < 0 || match.rm_eo < 0)
1160 return 0;
@@ -1158,19 +1169,26 @@ static int match_next_pattern(struct grep_pat *p,
1169 return 1;
1170 }
1171
1161 -static int next_match(struct grep_opt *opt,
1162 - const char *bol, const char *eol,
1163 - enum grep_context ctx, regmatch_t *pmatch, int eflags)
1172 +int grep_next_match(struct grep_opt *opt,
1173 + const char *bol, const char *eol,
1174 + enum grep_context ctx, regmatch_t *pmatch,
1175 + enum grep_header_field field, int eflags)
1176 {
1177 struct grep_pat *p;
1178 int hit = 0;
1179
1180 pmatch->rm_so = pmatch->rm_eo = -1;
1181 if (bol < eol) {
1170 - for (p = opt->pattern_list; p; p = p->next) {
1182 + for (p = ((ctx == GREP_CONTEXT_HEAD)
1183 + ? opt->header_list : opt->pattern_list);
1184 + p; p = p->next) {
1185 switch (p->token) {
1172 - case GREP_PATTERN: /* atom */
1186 case GREP_PATTERN_HEAD:
1187 + if ((field != GREP_HEADER_FIELD_MAX) &&
1188 + (p->field != field))
1189 + continue;
1190 + /* fall thru */
1191 + case GREP_PATTERN: /* atom */
1192 case GREP_PATTERN_BODY:
1193 hit |= match_next_pattern(p, bol, eol, ctx,
1194 pmatch, eflags);
@@ -1261,7 +1279,8 @@ static void show_line(struct grep_opt *opt,
1279 else if (sign == '=')
1280 line_color = opt->colors[GREP_COLOR_FUNCTION];
1281 }
1264 - while (next_match(opt, bol, eol, ctx, &match, eflags)) {
1282 + while (grep_next_match(opt, bol, eol, ctx, &match,
1283 + GREP_HEADER_FIELD_MAX, eflags)) {
1284 if (match.rm_so == match.rm_eo)
1285 break;
1286
grep.h
+9
@@ -191,6 +191,15 @@ void compile_grep_patterns(struct grep_opt *opt);
191 void free_grep_patterns(struct grep_opt *opt);
192 int grep_buffer(struct grep_opt *opt, const char *buf, unsigned long size);
193
194 +/* The field parameter is only used to filter header patterns
195 + * (where appropriate). If filtering isn't desirable
196 + * GREP_HEADER_FIELD_MAX should be supplied.
197 + */
198 +int grep_next_match(struct grep_opt *opt,
199 + const char *bol, const char *eol,
200 + enum grep_context ctx, regmatch_t *pmatch,
201 + enum grep_header_field field, int eflags);
202 +
203 struct grep_source {
204 char *name;
205