diff options
Diffstat (limited to 'grep.c')
-rw-r--r-- | grep.c | 65 |
1 files changed, 53 insertions, 12 deletions
@@ -189,17 +189,32 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list) return compile_pattern_or(list); } +static struct grep_expr *grep_true_expr(void) +{ + struct grep_expr *z = xcalloc(1, sizeof(*z)); + z->node = GREP_NODE_TRUE; + return z; +} + +static struct grep_expr *grep_or_expr(struct grep_expr *left, struct grep_expr *right) +{ + struct grep_expr *z = xcalloc(1, sizeof(*z)); + z->node = GREP_NODE_OR; + z->u.binary.left = left; + z->u.binary.right = right; + return z; +} + static struct grep_expr *prep_header_patterns(struct grep_opt *opt) { struct grep_pat *p; struct grep_expr *header_expr; + struct grep_expr *(header_group[GREP_HEADER_FIELD_MAX]); + enum grep_header_field fld; if (!opt->header_list) return NULL; p = opt->header_list; - header_expr = compile_pattern_expr(&p); - if (p) - die("incomplete pattern expression: %s", p->pattern); for (p = opt->header_list; p; p = p->next) { if (p->token != GREP_PATTERN_HEAD) die("bug: a non-header pattern in grep header list."); @@ -207,6 +222,33 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt) die("bug: unknown header field %d", p->field); compile_regexp(p, opt); } + + for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++) + header_group[fld] = NULL; + + for (p = opt->header_list; p; p = p->next) { + struct grep_expr *h; + struct grep_pat *pp = p; + + h = compile_pattern_atom(&pp); + if (!h || pp != p->next) + die("bug: malformed header expr"); + if (!header_group[p->field]) { + header_group[p->field] = h; + continue; + } + header_group[p->field] = grep_or_expr(h, header_group[p->field]); + } + + header_expr = NULL; + + for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++) { + if (!header_group[fld]) + continue; + if (!header_expr) + header_expr = grep_true_expr(); + header_expr = grep_or_expr(header_group[fld], header_expr); + } return header_expr; } @@ -242,22 +284,18 @@ void compile_grep_patterns(struct grep_opt *opt) if (!header_expr) return; - if (opt->pattern_expression) { - struct grep_expr *z; - z = xcalloc(1, sizeof(*z)); - z->node = GREP_NODE_OR; - z->u.binary.left = opt->pattern_expression; - z->u.binary.right = header_expr; - opt->pattern_expression = z; - } else { + if (!opt->pattern_expression) opt->pattern_expression = header_expr; - } + else + opt->pattern_expression = grep_or_expr(opt->pattern_expression, + header_expr); opt->all_match = 1; } static void free_pattern_expr(struct grep_expr *x) { switch (x->node) { + case GREP_NODE_TRUE: case GREP_NODE_ATOM: break; case GREP_NODE_NOT: @@ -486,6 +524,9 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol, if (!x) die("Not a valid grep expression"); switch (x->node) { + case GREP_NODE_TRUE: + h = 1; + break; case GREP_NODE_ATOM: h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0); break; |