Skip to content

Commit 68d686e

Browse files
ttaylorrpeff
authored andcommitted
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 <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f8a0c6e commit 68d686e

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

grep.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,11 +1248,11 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
12481248
return hit;
12491249
}
12501250

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)
12531254
{
12541255
int h = 0;
1255-
regmatch_t match;
12561256

12571257
if (!x)
12581258
die("Not a valid grep expression");
@@ -1261,25 +1261,39 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
12611261
h = 1;
12621262
break;
12631263
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+
}
12651271
break;
12661272
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);
12681278
break;
12691279
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))
12711282
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);
12731285
break;
12741286
case GREP_NODE_OR:
12751287
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);
12811294
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);
12831297
break;
12841298
default:
12851299
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,
12901304
}
12911305

12921306
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)
12941309
{
12951310
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);
12971312
}
12981313

12991314
static int match_line(struct grep_opt *opt, char *bol, char *eol,
1315+
ssize_t *col, ssize_t *icol,
13001316
enum grep_context ctx, int collect_hits)
13011317
{
13021318
struct grep_pat *p;
1303-
regmatch_t match;
13041319

13051320
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);
13071323

13081324
/* we do not call with collect_hits without being extended */
13091325
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;
13111329
return 1;
1330+
}
13121331
}
13131332
return 0;
13141333
}
@@ -1763,6 +1782,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
17631782
while (left) {
17641783
char *eol, ch;
17651784
int hit;
1785+
ssize_t col = -1, icol = -1;
17661786

17671787
/*
17681788
* 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
17861806
if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
17871807
ctx = GREP_CONTEXT_BODY;
17881808

1789-
hit = match_line(opt, bol, eol, ctx, collect_hits);
1809+
hit = match_line(opt, bol, eol, &col, &icol, ctx, collect_hits);
17901810
*eol = ch;
17911811

17921812
if (collect_hits)

0 commit comments

Comments
 (0)