summaryrefslogtreecommitdiff
path: root/grep.c
diff options
context:
space:
mode:
Diffstat (limited to 'grep.c')
-rw-r--r--grep.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/grep.c b/grep.c
index 718a3c2346..63c4280cac 100644
--- a/grep.c
+++ b/grep.c
@@ -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;