diff options
-rw-r--r-- | grep.c | 79 | ||||
-rw-r--r-- | grep.h | 9 |
2 files changed, 58 insertions, 30 deletions
@@ -944,10 +944,10 @@ static struct { { "reflog ", 7 }, }; -static int match_one_pattern(struct grep_pat *p, - const char *bol, const char *eol, - enum grep_context ctx, - regmatch_t *pmatch, int eflags) +static int headerless_match_one_pattern(struct grep_pat *p, + const char *bol, const char *eol, + enum grep_context ctx, + regmatch_t *pmatch, int eflags) { int hit = 0; const char *start = bol; @@ -956,25 +956,6 @@ static int match_one_pattern(struct grep_pat *p, ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD))) return 0; - if (p->token == GREP_PATTERN_HEAD) { - const char *field; - size_t len; - assert(p->field < ARRAY_SIZE(header_field)); - field = header_field[p->field].field; - len = header_field[p->field].len; - if (strncmp(bol, field, len)) - return 0; - bol += len; - switch (p->field) { - case GREP_HEADER_AUTHOR: - case GREP_HEADER_COMMITTER: - strip_timestamp(bol, &eol); - break; - default: - break; - } - } - again: hit = patmatch(p, bol, eol, pmatch, eflags); @@ -1025,6 +1006,36 @@ static int match_one_pattern(struct grep_pat *p, return hit; } +static int match_one_pattern(struct grep_pat *p, + const char *bol, const char *eol, + enum grep_context ctx, regmatch_t *pmatch, + int eflags) +{ + const char *field; + size_t len; + + if (p->token == GREP_PATTERN_HEAD) { + assert(p->field < ARRAY_SIZE(header_field)); + field = header_field[p->field].field; + len = header_field[p->field].len; + if (strncmp(bol, field, len)) + return 0; + bol += len; + + switch (p->field) { + case GREP_HEADER_AUTHOR: + case GREP_HEADER_COMMITTER: + strip_timestamp(bol, &eol); + break; + default: + break; + } + } + + return headerless_match_one_pattern(p, bol, eol, ctx, pmatch, eflags); +} + + static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x, const char *bol, const char *eol, enum grep_context ctx, ssize_t *col, @@ -1143,7 +1154,7 @@ static int match_next_pattern(struct grep_pat *p, { regmatch_t match; - if (!match_one_pattern(p, bol, eol, ctx, &match, eflags)) + if (!headerless_match_one_pattern(p, bol, eol, ctx, &match, eflags)) return 0; if (match.rm_so < 0 || match.rm_eo < 0) return 0; @@ -1158,19 +1169,26 @@ static int match_next_pattern(struct grep_pat *p, return 1; } -static int next_match(struct grep_opt *opt, - const char *bol, const char *eol, - enum grep_context ctx, regmatch_t *pmatch, int eflags) +int grep_next_match(struct grep_opt *opt, + const char *bol, const char *eol, + enum grep_context ctx, regmatch_t *pmatch, + enum grep_header_field field, int eflags) { struct grep_pat *p; int hit = 0; pmatch->rm_so = pmatch->rm_eo = -1; if (bol < eol) { - for (p = opt->pattern_list; p; p = p->next) { + for (p = ((ctx == GREP_CONTEXT_HEAD) + ? opt->header_list : opt->pattern_list); + p; p = p->next) { switch (p->token) { - case GREP_PATTERN: /* atom */ case GREP_PATTERN_HEAD: + if ((field != GREP_HEADER_FIELD_MAX) && + (p->field != field)) + continue; + /* fall thru */ + case GREP_PATTERN: /* atom */ case GREP_PATTERN_BODY: hit |= match_next_pattern(p, bol, eol, ctx, pmatch, eflags); @@ -1261,7 +1279,8 @@ static void show_line(struct grep_opt *opt, else if (sign == '=') line_color = opt->colors[GREP_COLOR_FUNCTION]; } - while (next_match(opt, bol, eol, ctx, &match, eflags)) { + while (grep_next_match(opt, bol, eol, ctx, &match, + GREP_HEADER_FIELD_MAX, eflags)) { if (match.rm_so == match.rm_eo) break; @@ -191,6 +191,15 @@ void compile_grep_patterns(struct grep_opt *opt); void free_grep_patterns(struct grep_opt *opt); int grep_buffer(struct grep_opt *opt, const char *buf, unsigned long size); +/* The field parameter is only used to filter header patterns + * (where appropriate). If filtering isn't desirable + * GREP_HEADER_FIELD_MAX should be supplied. + */ +int grep_next_match(struct grep_opt *opt, + const char *bol, const char *eol, + enum grep_context ctx, regmatch_t *pmatch, + enum grep_header_field field, int eflags); + struct grep_source { char *name; |