From 3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 20 Sep 2008 00:52:11 -0700 Subject: [PATCH] diff: fix "multiple regexp" semantics to find hunk header comment When multiple regular expressions are concatenated with "\n", they were traditionally AND'ed together, and only a line that matches _all_ of them is taken as a match. This however is unwieldy when multiple regexp feature is used to specify alternatives. This fixes the semantics to take the first match. A nagative pattern, if matches, makes the line to fail as before. A match with a positive pattern will be the final match, and what it captures in $1 is used as the hunk header comment. We could write alternatives using "|" in ERE, but the machinery can only use captured $1 as the hunk header comment (or $0 if there is no match in $1), so you cannot write: "junk ( A | B ) | garbage ( C | D )" and expect both "junk" and "garbage" to get stripped with the existing code. With this fix, you can write it as: "junk ( A | B ) \n garbage ( C | D )" and the way capture works would match the user expectation more naturally. Signed-off-by: Junio C Hamano --- diff.c | 2 +- xdiff-interface.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/diff.c b/diff.c index a73301017..1bcbbd5bb 100644 --- a/diff.c +++ b/diff.c @@ -1414,7 +1414,7 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "pascal", "^((procedure|function|constructor|destructor|interface|" "implementation|initialization|finalization)[ \t]*.*)$" - "|" + "\n" "^(.*=[ \t]*(class|record).*)$", REG_EXTENDED }, { "php", "^[\t ]*((function|class).*)", REG_EXTENDED }, diff --git a/xdiff-interface.c b/xdiff-interface.c index 7f1a7d3ff..6c6bb1997 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -194,26 +194,29 @@ static long ff_regexp(const char *line, long len, char *line_buffer = xstrndup(line, len); /* make NUL terminated */ struct ff_regs *regs = priv; regmatch_t pmatch[2]; - int result = 0, i; + int i; + int result = -1; for (i = 0; i < regs->nr; i++) { struct ff_reg *reg = regs->array + i; - if (reg->negate ^ !!regexec(®->re, - line_buffer, 2, pmatch, 0)) { - free(line_buffer); - return -1; + if (!regexec(®->re, line_buffer, 2, pmatch, 0)) { + if (reg->negate) + goto fail; + break; } } + if (regs->nr <= i) + goto fail; i = pmatch[1].rm_so >= 0 ? 1 : 0; line += pmatch[i].rm_so; result = pmatch[i].rm_eo - pmatch[i].rm_so; if (result > buffer_size) result = buffer_size; else - while (result > 0 && (isspace(line[result - 1]) || - line[result - 1] == '\n')) + while (result > 0 && (isspace(line[result - 1]))) result--; memcpy(buffer, line, result); + fail: free(line_buffer); return result; } -- 2.30.2