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

[PATCH 2/7] grep.c: expose {,inverted} match column in match_line()

From
Taylor Blau <me@ttaylorr.com>
Date
Jun 18, 2018, 23:43 UTC
Message-ID
<d0a6b3ca2a8e67c6a5ed4d2c56c5121d4bc3554b.1529365072.git.me@ttaylorr.com>
In-Reply-To
<cover.1529365072.git.me@ttaylorr.com>

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, with the exception that --or is
    short-circuiting. For instance, if we match "-e a --or -e b" on a
    line that contains both "a" and "b" (and "b" comes first), the match
    column will hold "a", since we inspected the left child first, and
    short-circuited over the right child.

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>
---
 grep.c | 56 ++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 18 deletions(-)
diff --git a/grep.c b/grep.c
index 45ec7e636c..19c782aa9d 100644
--- a/grep.c
+++ b/grep.c
@@ -1249,10 +1249,10 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 }
 
 static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
-			   enum grep_context ctx, int collect_hits)
+			   enum grep_context ctx, ssize_t *col,
+			   ssize_t *icol, int collect_hits)
 {
 	int h = 0;
-	regmatch_t match;
 
 	if (!x)
 		die("Not a valid grep expression");
@@ -1261,25 +1261,39 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
 		h = 1;
 		break;
 	case GREP_NODE_ATOM:
-		h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
+		{
+			regmatch_t tmp;
+			h = match_one_pattern(x->u.atom, bol, eol, ctx,
+					      &tmp, 0);
+			if (h && (*col < 0 || tmp.rm_so < *col))
+				*col = tmp.rm_so;
+		}
 		break;
 	case GREP_NODE_NOT:
-		h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
+		/*
+		 * Upon visiting a GREP_NODE_NOT, imatch and match become
+		 * swapped.
+		 */
+		h = !match_expr_eval(x->u.unary, bol, eol, ctx, icol, col, 0);
 		break;
 	case GREP_NODE_AND:
-		if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
+		if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, col,
+				     icol, 0))
 			return 0;
-		h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
+		h = match_expr_eval(x->u.binary.right, bol, eol, ctx, col,
+				    icol, 0);
 		break;
 	case GREP_NODE_OR:
 		if (!collect_hits)
-			return (match_expr_eval(x->u.binary.left,
-						bol, eol, ctx, 0) ||
-				match_expr_eval(x->u.binary.right,
-						bol, eol, ctx, 0));
-		h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
+			return (match_expr_eval(x->u.binary.left, bol, eol, ctx,
+						col, icol, 0) ||
+				match_expr_eval(x->u.binary.right, bol, eol,
+						ctx, col, icol, 0));
+		h = match_expr_eval(x->u.binary.left, bol, eol, ctx, col,
+				    icol, 0);
 		x->u.binary.left->hit |= h;
-		h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
+		h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, col,
+				     icol, 1);
 		break;
 	default:
 		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,
 }
 
 static int match_expr(struct grep_opt *opt, char *bol, char *eol,
-		      enum grep_context ctx, int collect_hits)
+		      enum grep_context ctx, ssize_t *col,
+		      ssize_t *icol, int collect_hits)
 {
 	struct grep_expr *x = opt->pattern_expression;
-	return match_expr_eval(x, bol, eol, ctx, collect_hits);
+	return match_expr_eval(x, bol, eol, ctx, col, icol, collect_hits);
 }
 
 static int match_line(struct grep_opt *opt, char *bol, char *eol,
+		      ssize_t *col, ssize_t *icol,
 		      enum grep_context ctx, int collect_hits)
 {
 	struct grep_pat *p;
-	regmatch_t match;
 
 	if (opt->extended)
-		return match_expr(opt, bol, eol, ctx, collect_hits);
+		return match_expr(opt, bol, eol, ctx, col, icol,
+				  collect_hits);
 
 	/* we do not call with collect_hits without being extended */
 	for (p = opt->pattern_list; p; p = p->next) {
-		if (match_one_pattern(p, bol, eol, ctx, &match, 0))
+		regmatch_t tmp;
+		if (match_one_pattern(p, bol, eol, ctx, &tmp, 0)) {
+			*col = tmp.rm_so;
 			return 1;
+		}
 	}
 	return 0;
 }
@@ -1763,6 +1782,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
 	while (left) {
 		char *eol, ch;
 		int hit;
+		ssize_t col = -1, icol = -1;
 
 		/*
 		 * 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
 		if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
 			ctx = GREP_CONTEXT_BODY;
 
-		hit = match_line(opt, bol, eol, ctx, collect_hits);
+		hit = match_line(opt, bol, eol, &col, &icol, ctx, collect_hits);
 		*eol = ch;
 
 		if (collect_hits)
-- 
2.17.0.582.gccdcbd54c
Previous: Taylor BlauNext: Junio C Hamano
Message 3 of 56 in “grep.c: teach --column to 'git-grep(1)'”
  1. 0/7 grep.c: teach --column to 'git-grep(1)'Taylor Blau, Jun 18, 2018
  2. 1/7 Documentation/config.txt: camel-case lineNumber for consistencyTaylor Blau, Jun 18, 2018
  3. 2/7 grep.c: expose {,inverted} match column in match_line()Taylor Blau, Jun 18, 2018
  4. Junio C HamanoJun 19, 2018
  5. Taylor BlauJun 19, 2018
  6. 3/7 grep.[ch]: extend grep_opt to allow showing matched columnTaylor Blau, Jun 18, 2018
  7. 4/7 grep.c: display column number of first matchTaylor Blau, Jun 18, 2018
  8. Jeff KingJun 19, 2018
  9. Taylor BlauJun 19, 2018
  10. 5/7 builtin/grep.c: add '--column' option to 'git-grep(1)'Taylor Blau, Jun 18, 2018
  11. 6/7 grep.c: add configuration variables to show matched optionTaylor Blau, Jun 18, 2018
  12. 7/7 contrib/git-jump/git-jump: jump to exact locationTaylor Blau, Jun 18, 2018
  13. Jeff KingJun 19, 2018
  14. René ScharfeJun 19, 2018
  15. Taylor BlauJun 19, 2018
  16. René ScharfeJun 19, 2018
  17. René ScharfeJun 19, 2018
  18. Jeff KingJun 19, 2018
  19. Taylor BlauJun 19, 2018
  20. Junio C HamanoJun 19, 2018
  21. Taylor BlauJun 19, 2018
  22. Jeff KingJun 19, 2018
  23. Junio C HamanoJun 19, 2018
  24. René ScharfeJun 19, 2018
  25. Jeff KingJun 19, 2018
  26. René ScharfeJun 19, 2018
  27. Junio C HamanoJun 19, 2018
  28. Junio C HamanoJun 19, 2018
  29. Taylor BlauJun 19, 2018
  30. Taylor BlauJun 19, 2018
  31. 0/7 grep.c: teach --column to 'git-grep(1)'Taylor Blau, Jun 20, 2018
  32. 1/7 Documentation/config.txt: camel-case lineNumber for consistencyTaylor Blau, Jun 20, 2018
  33. 2/7 grep.c: expose {,inverted} match column in match_line()Taylor Blau, Jun 20, 2018
  34. 3/7 grep.[ch]: extend grep_opt to allow showing matched columnTaylor Blau, Jun 20, 2018
  35. 4/7 grep.c: display column number of first matchTaylor Blau, Jun 20, 2018
  36. 6/7 grep.c: add configuration variables to show matched optionTaylor Blau, Jun 20, 2018
  37. 7/7 contrib/git-jump/git-jump: jump to exact locationTaylor Blau, Jun 20, 2018
  38. 5/7 builtin/grep.c: add '--column' option to 'git-grep(1)'Taylor Blau, Jun 20, 2018
  39. Jeff KingJun 21, 2018
  40. Jeff KingJun 21, 2018
  41. Johannes SchindelinJun 22, 2018
  42. Jeff KingJun 22, 2018
  43. Junio C HamanoJun 21, 2018
  44. Taylor BlauJun 21, 2018
  45. Jeff KingJun 22, 2018
  46. 0/7 grep.c: teach --column to 'git-grep(1)'Taylor Blau, Jun 22, 2018
  47. 1/7 Documentation/config.txt: camel-case lineNumber for consistencyTaylor Blau, Jun 22, 2018
  48. 2/7 grep.c: expose {,inverted} match column in match_line()Taylor Blau, Jun 22, 2018
  49. 3/7 grep.[ch]: extend grep_opt to allow showing matched columnTaylor Blau, Jun 22, 2018
  50. 4/7 grep.c: display column number of first matchTaylor Blau, Jun 22, 2018
  51. 5/7 builtin/grep.c: add '--column' option to 'git-grep(1)'Taylor Blau, Jun 22, 2018
  52. 7/7 contrib/git-jump/git-jump: jump to exact locationTaylor Blau, Jun 22, 2018
  53. 6/7 grep.c: add configuration variables to show matched optionTaylor Blau, Jun 22, 2018
  54. Jeff KingJun 25, 2018
  55. Taylor BlauJun 25, 2018
  56. Junio C HamanoJun 26, 2018

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.