grep.c: expose {,inverted} match column in match_line()

When calling match_line(), callers presently cannot determine the relative offset of the match because match_line() discards the 'regmatch_t' that contains this information. Instead, teach match_line() to take in two 'ssize_t's. Fill the first with the offset of the match produced by the given expression. If extended, fill the later with the offset of the match produced as if --invert were given. For instance, matching "--not -e x" on this line produces a columnar offset of 0, (i.e., the whole line does not contain an x), but "--invert --not -e -x" will fill the later ssize_t of the column containing an "x", because this expression is semantically equivalent to "-e x". To determine the column for the inverted and non-inverted case, do the following: - If matching an atom, the non-inverted column is as given from match_one_pattern(), and the inverted column is unset. - If matching a --not, the inverted column and non-inverted column swap. - If matching an --and, or --or, the non-inverted column is the minimum of the two children. Presently, the existing short-circuiting logic for AND and OR applies as before. This will change in the following commit when we add options to configure the --column flag. Taken together, this and the forthcoming change will always yield the earlier column on a given line. This patch will become useful when we later pick between the two new results in order to display the column number of the first match on a line with --column. Co-authored-by: Jeff King <peff@peff.net> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Jun 22, 2018 at 10:49 UTC 68d686e6af0fc192fce1788f67bbe0c21a5419ab
1 file changed +39 -19
grep.c
+39 -19
@@ -1248,11 +1248,11 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
1248 return hit;
1249 }
1250
1251 -static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
1252 - enum grep_context ctx, int collect_hits)
1251 +static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x, char *bol,
1252 + char *eol, enum grep_context ctx, ssize_t *col,
1253 + ssize_t *icol, int collect_hits)
1254 {
1255 int h = 0;
1255 - regmatch_t match;
1256
1257 if (!x)
1258 die("Not a valid grep expression");
@@ -1261,25 +1261,39 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
1261 h = 1;
1262 break;
1263 case GREP_NODE_ATOM:
1264 - h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
1264 + {
1265 + regmatch_t tmp;
1266 + h = match_one_pattern(x->u.atom, bol, eol, ctx,
1267 + &tmp, 0);
1268 + if (h && (*col < 0 || tmp.rm_so < *col))
1269 + *col = tmp.rm_so;
1270 + }
1271 break;
1272 case GREP_NODE_NOT:
1267 - h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
1273 + /*
1274 + * Upon visiting a GREP_NODE_NOT, col and icol become swapped.
1275 + */
1276 + h = !match_expr_eval(opt, x->u.unary, bol, eol, ctx, icol, col,
1277 + 0);
1278 break;
1279 case GREP_NODE_AND:
1270 - if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
1280 + if (!match_expr_eval(opt, x->u.binary.left, bol, eol, ctx, col,
1281 + icol, 0))
1282 return 0;
1272 - h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
1283 + h = match_expr_eval(opt, x->u.binary.right, bol, eol, ctx, col,
1284 + icol, 0);
1285 break;
1286 case GREP_NODE_OR:
1287 if (!collect_hits)
1276 - return (match_expr_eval(x->u.binary.left,
1277 - bol, eol, ctx, 0) ||
1278 - match_expr_eval(x->u.binary.right,
1279 - bol, eol, ctx, 0));
1280 - h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
1288 + return (match_expr_eval(opt, x->u.binary.left, bol, eol,
1289 + ctx, col, icol, 0) ||
1290 + match_expr_eval(opt, x->u.binary.right, bol,
1291 + eol, ctx, col, icol, 0));
1292 + h = match_expr_eval(opt, x->u.binary.left, bol, eol, ctx, col,
1293 + icol, 0);
1294 x->u.binary.left->hit |= h;
1282 - h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
1295 + h |= match_expr_eval(opt, x->u.binary.right, bol, eol, ctx, col,
1296 + icol, 1);
1297 break;
1298 default:
1299 die("Unexpected node type (internal error) %d", x->node);
@@ -1290,25 +1304,30 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
1304 }
1305
1306 static int match_expr(struct grep_opt *opt, char *bol, char *eol,
1293 - enum grep_context ctx, int collect_hits)
1307 + enum grep_context ctx, ssize_t *col,
1308 + ssize_t *icol, int collect_hits)
1309 {
1310 struct grep_expr *x = opt->pattern_expression;
1296 - return match_expr_eval(x, bol, eol, ctx, collect_hits);
1311 + return match_expr_eval(opt, x, bol, eol, ctx, col, icol, collect_hits);
1312 }
1313
1314 static int match_line(struct grep_opt *opt, char *bol, char *eol,
1315 + ssize_t *col, ssize_t *icol,
1316 enum grep_context ctx, int collect_hits)
1317 {
1318 struct grep_pat *p;
1303 - regmatch_t match;
1319
1320 if (opt->extended)
1306 - return match_expr(opt, bol, eol, ctx, collect_hits);
1321 + return match_expr(opt, bol, eol, ctx, col, icol,
1322 + collect_hits);
1323
1324 /* we do not call with collect_hits without being extended */
1325 for (p = opt->pattern_list; p; p = p->next) {
1310 - if (match_one_pattern(p, bol, eol, ctx, &match, 0))
1326 + regmatch_t tmp;
1327 + if (match_one_pattern(p, bol, eol, ctx, &tmp, 0)) {
1328 + *col = tmp.rm_so;
1329 return 1;
1330 + }
1331 }
1332 return 0;
1333 }
@@ -1763,6 +1782,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
1782 while (left) {
1783 char *eol, ch;
1784 int hit;
1785 + ssize_t col = -1, icol = -1;
1786
1787 /*
1788 * look_ahead() skips quickly to the line that possibly
@@ -1786,7 +1806,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
1806 if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
1807 ctx = GREP_CONTEXT_BODY;
1808
1789 - hit = match_line(opt, bol, eol, ctx, collect_hits);
1809 + hit = match_line(opt, bol, eol, &col, &icol, ctx, collect_hits);
1810 *eol = ch;
1811
1812 if (collect_hits)