{"thread":{"id":"19629","subject":"[PATCH] grep: fix colouring of matches with zero length","startedAt":"2009-06-01T16:46:18Z","lastAt":"2009-06-01T21:53:05Z","messageCount":3,"participants":["René Scharfe","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"115211","messageId":"4A2405DA.7010801@lsrfire.ath.cx","threadId":"19629","inReplyTo":null,"subject":"[PATCH] grep: fix colouring of matches with zero length","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-06-01T16:46:18Z","receivedAt":"2009-06-01T16:46:18Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"The first hunk fixes match colouring if the patterns is the empty string.\nSuch a pattern matches the whole line, but fixmatch() sets the end offset\nto the same value as the start offset.  Special case the empty pattern in\nmatch_one_pattern() and thus avoid calling fixmatch().\n\nThe second hunk of the patch makes sure that grep match colouring doesn't\nget stuck in an infinite loop if the length of a match is zero.  The rest\nof the line is simply printed without colouring.  Even though the empty\npattern string doesn't result in empty matches any more, this defensive\nmeasure catches unknown cases.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n grep.c |    8 +++++++-\n 1 files changed, 7 insertions(+), 1 deletions(-)\n\ndiff --git a/grep.c b/grep.c\nindex cc6d5b0..745b3c0 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -324,7 +324,11 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,\n \t}\n \n  again:\n-\tif (p->fixed)\n+\tif (p->pattern[0] == '\\0') {\n+\t\thit = 1;\n+\t\tpmatch[0].rm_so = 0;\n+\t\tpmatch[0].rm_eo = eol - bol;\n+\t} else if (p->fixed)\n \t\thit = !fixmatch(p->pattern, bol, pmatch);\n \telse\n \t\thit = !regexec(&p->regexp, bol, 1, pmatch, eflags);\n@@ -500,6 +504,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,\n \n \t\t*eol = '\\0';\n \t\twhile (next_match(opt, bol, eol, ctx, &match, eflags)) {\n+\t\t\tif (match.rm_so == match.rm_eo)\n+\t\t\t\tbreak;\n \t\t\tprintf(\"%.*s%s%.*s%s\",\n \t\t\t       (int)match.rm_so, bol,\n \t\t\t       opt->color_match,\n-- \n1.6.3.1\n"},{"id":"115215","messageId":"7voct7k61r.fsf@alter.siamese.dyndns.org","threadId":"19629","inReplyTo":"4A2405DA.7010801@lsrfire.ath.cx","subject":"Re: [PATCH] grep: fix colouring of matches with zero length","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-06-01T21:17:20Z","receivedAt":"2009-06-01T21:17:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> The first hunk fixes match colouring if the patterns is the empty string.\n> Such a pattern matches the whole line,...\n\nHmmm...\n\nAn empty pattern may have to produce a match with any line, but I do not\nthink it should match the whole line.  GNU seems to agree with me.\n\n\techo foo | grep --color -e ''\n        echo foo | grep --color -F -e ''\n        echo foo | grep --color -e '.*'\n        echo foo | grep --color -F -e 'foo'\n\nThe first two are uncoloured (but still show matches).\n\n> The second hunk of the patch makes sure that grep match colouring doesn't\n> get stuck in an infinite loop if the length of a match is zero.\n\nCertainly we need to advance the match pointer, and this issue needs to be\naddressed.  I think it is a good change.\n\n> of the line is simply printed without colouring.  Even though the empty\n> pattern string doesn't result in empty matches any more, this defensive\n> measure catches unknown cases.\n>\n> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n> ---\n>  grep.c |    8 +++++++-\n>  1 files changed, 7 insertions(+), 1 deletions(-)\n>\n> diff --git a/grep.c b/grep.c\n> index cc6d5b0..745b3c0 100644\n> --- a/grep.c\n> +++ b/grep.c\n> @@ -324,7 +324,11 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,\n>  \t}\n>  \n>   again:\n> -\tif (p->fixed)\n> +\tif (p->pattern[0] == '\\0') {\n> +\t\thit = 1;\n> +\t\tpmatch[0].rm_so = 0;\n> +\t\tpmatch[0].rm_eo = eol - bol;\n> +\t} else if (p->fixed)\n>  \t\thit = !fixmatch(p->pattern, bol, pmatch);\n>  \telse\n>  \t\thit = !regexec(&p->regexp, bol, 1, pmatch, eflags);\n> @@ -500,6 +504,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,\n>  \n>  \t\t*eol = '\\0';\n>  \t\twhile (next_match(opt, bol, eol, ctx, &match, eflags)) {\n> +\t\t\tif (match.rm_so == match.rm_eo)\n> +\t\t\t\tbreak;\n>  \t\t\tprintf(\"%.*s%s%.*s%s\",\n>  \t\t\t       (int)match.rm_so, bol,\n>  \t\t\t       opt->color_match,\n> -- \n> 1.6.3.1\n"},{"id":"115217","messageId":"4A244DC1.1090801@lsrfire.ath.cx","threadId":"19629","inReplyTo":"7voct7k61r.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] grep: fix colouring of matches with zero length","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2009-06-01T21:53:05Z","receivedAt":"2009-06-01T21:53:05Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n> \n>> The first hunk fixes match colouring if the patterns is the empty string.\n>> Such a pattern matches the whole line,...\n> \n> Hmmm...\n> \n> An empty pattern may have to produce a match with any line, but I do not\n> think it should match the whole line.  GNU seems to agree with me.\n> \n> \techo foo | grep --color -e ''\n>         echo foo | grep --color -F -e ''\n>         echo foo | grep --color -e '.*'\n>         echo foo | grep --color -F -e 'foo'\n> \n> The first two are uncoloured (but still show matches).\n\nYou're right, and matching the zero-length string at the beginning of the\nline actually makes sense.  Corrected patch below.\n\n\nIf a zero-length match is encountered, break out of loop and show the rest\nof the line uncoloured.  Otherwise we'd be looping forever, trying to make\nprogress by advancing the pointer by zero characters.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n grep.c |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\ndiff --git a/grep.c b/grep.c\nindex cc6d5b0..7bf4a60 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -500,6 +500,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,\n \n \t\t*eol = '\\0';\n \t\twhile (next_match(opt, bol, eol, ctx, &match, eflags)) {\n+\t\t\tif (match.rm_so == match.rm_eo)\n+\t\t\t\tbreak;\n \t\t\tprintf(\"%.*s%s%.*s%s\",\n \t\t\t       (int)match.rm_so, bol,\n \t\t\t       opt->color_match,\n-- \n1.6.3.1\n"}]}