Code

make "git var" a built-in
[git.git] / grep.c
1 #include "cache.h"
2 #include "grep.h"
3 #include "userdiff.h"
4 #include "xdiff-interface.h"
6 void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
7 {
8         struct grep_pat *p = xcalloc(1, sizeof(*p));
9         p->pattern = pat;
10         p->origin = "header";
11         p->no = 0;
12         p->token = GREP_PATTERN_HEAD;
13         p->field = field;
14         *opt->pattern_tail = p;
15         opt->pattern_tail = &p->next;
16         p->next = NULL;
17 }
19 void append_grep_pattern(struct grep_opt *opt, const char *pat,
20                          const char *origin, int no, enum grep_pat_token t)
21 {
22         struct grep_pat *p = xcalloc(1, sizeof(*p));
23         p->pattern = pat;
24         p->origin = origin;
25         p->no = no;
26         p->token = t;
27         *opt->pattern_tail = p;
28         opt->pattern_tail = &p->next;
29         p->next = NULL;
30 }
32 static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
33 {
34         int err;
36         p->word_regexp = opt->word_regexp;
37         p->ignore_case = opt->ignore_case;
39         if (opt->fixed)
40                 p->fixed = 1;
41         if (opt->regflags & REG_ICASE)
42                 p->fixed = 0;
43         if (p->fixed)
44                 return;
46         err = regcomp(&p->regexp, p->pattern, opt->regflags);
47         if (err) {
48                 char errbuf[1024];
49                 char where[1024];
50                 if (p->no)
51                         sprintf(where, "In '%s' at %d, ",
52                                 p->origin, p->no);
53                 else if (p->origin)
54                         sprintf(where, "%s, ", p->origin);
55                 else
56                         where[0] = 0;
57                 regerror(err, &p->regexp, errbuf, 1024);
58                 regfree(&p->regexp);
59                 die("%s'%s': %s", where, p->pattern, errbuf);
60         }
61 }
63 static struct grep_expr *compile_pattern_or(struct grep_pat **);
64 static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
65 {
66         struct grep_pat *p;
67         struct grep_expr *x;
69         p = *list;
70         if (!p)
71                 return NULL;
72         switch (p->token) {
73         case GREP_PATTERN: /* atom */
74         case GREP_PATTERN_HEAD:
75         case GREP_PATTERN_BODY:
76                 x = xcalloc(1, sizeof (struct grep_expr));
77                 x->node = GREP_NODE_ATOM;
78                 x->u.atom = p;
79                 *list = p->next;
80                 return x;
81         case GREP_OPEN_PAREN:
82                 *list = p->next;
83                 x = compile_pattern_or(list);
84                 if (!*list || (*list)->token != GREP_CLOSE_PAREN)
85                         die("unmatched parenthesis");
86                 *list = (*list)->next;
87                 return x;
88         default:
89                 return NULL;
90         }
91 }
93 static struct grep_expr *compile_pattern_not(struct grep_pat **list)
94 {
95         struct grep_pat *p;
96         struct grep_expr *x;
98         p = *list;
99         if (!p)
100                 return NULL;
101         switch (p->token) {
102         case GREP_NOT:
103                 if (!p->next)
104                         die("--not not followed by pattern expression");
105                 *list = p->next;
106                 x = xcalloc(1, sizeof (struct grep_expr));
107                 x->node = GREP_NODE_NOT;
108                 x->u.unary = compile_pattern_not(list);
109                 if (!x->u.unary)
110                         die("--not followed by non pattern expression");
111                 return x;
112         default:
113                 return compile_pattern_atom(list);
114         }
117 static struct grep_expr *compile_pattern_and(struct grep_pat **list)
119         struct grep_pat *p;
120         struct grep_expr *x, *y, *z;
122         x = compile_pattern_not(list);
123         p = *list;
124         if (p && p->token == GREP_AND) {
125                 if (!p->next)
126                         die("--and not followed by pattern expression");
127                 *list = p->next;
128                 y = compile_pattern_and(list);
129                 if (!y)
130                         die("--and not followed by pattern expression");
131                 z = xcalloc(1, sizeof (struct grep_expr));
132                 z->node = GREP_NODE_AND;
133                 z->u.binary.left = x;
134                 z->u.binary.right = y;
135                 return z;
136         }
137         return x;
140 static struct grep_expr *compile_pattern_or(struct grep_pat **list)
142         struct grep_pat *p;
143         struct grep_expr *x, *y, *z;
145         x = compile_pattern_and(list);
146         p = *list;
147         if (x && p && p->token != GREP_CLOSE_PAREN) {
148                 y = compile_pattern_or(list);
149                 if (!y)
150                         die("not a pattern expression %s", p->pattern);
151                 z = xcalloc(1, sizeof (struct grep_expr));
152                 z->node = GREP_NODE_OR;
153                 z->u.binary.left = x;
154                 z->u.binary.right = y;
155                 return z;
156         }
157         return x;
160 static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
162         return compile_pattern_or(list);
165 void compile_grep_patterns(struct grep_opt *opt)
167         struct grep_pat *p;
169         if (opt->all_match)
170                 opt->extended = 1;
172         for (p = opt->pattern_list; p; p = p->next) {
173                 switch (p->token) {
174                 case GREP_PATTERN: /* atom */
175                 case GREP_PATTERN_HEAD:
176                 case GREP_PATTERN_BODY:
177                         compile_regexp(p, opt);
178                         break;
179                 default:
180                         opt->extended = 1;
181                         break;
182                 }
183         }
185         if (!opt->extended)
186                 return;
188         /* Then bundle them up in an expression.
189          * A classic recursive descent parser would do.
190          */
191         p = opt->pattern_list;
192         if (p)
193                 opt->pattern_expression = compile_pattern_expr(&p);
194         if (p)
195                 die("incomplete pattern expression: %s", p->pattern);
198 static void free_pattern_expr(struct grep_expr *x)
200         switch (x->node) {
201         case GREP_NODE_ATOM:
202                 break;
203         case GREP_NODE_NOT:
204                 free_pattern_expr(x->u.unary);
205                 break;
206         case GREP_NODE_AND:
207         case GREP_NODE_OR:
208                 free_pattern_expr(x->u.binary.left);
209                 free_pattern_expr(x->u.binary.right);
210                 break;
211         }
212         free(x);
215 void free_grep_patterns(struct grep_opt *opt)
217         struct grep_pat *p, *n;
219         for (p = opt->pattern_list; p; p = n) {
220                 n = p->next;
221                 switch (p->token) {
222                 case GREP_PATTERN: /* atom */
223                 case GREP_PATTERN_HEAD:
224                 case GREP_PATTERN_BODY:
225                         regfree(&p->regexp);
226                         break;
227                 default:
228                         break;
229                 }
230                 free(p);
231         }
233         if (!opt->extended)
234                 return;
235         free_pattern_expr(opt->pattern_expression);
238 static char *end_of_line(char *cp, unsigned long *left)
240         unsigned long l = *left;
241         while (l && *cp != '\n') {
242                 l--;
243                 cp++;
244         }
245         *left = l;
246         return cp;
249 static int word_char(char ch)
251         return isalnum(ch) || ch == '_';
254 static void show_name(struct grep_opt *opt, const char *name)
256         printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
260 static int fixmatch(const char *pattern, char *line, int ignore_case, regmatch_t *match)
262         char *hit;
263         if (ignore_case)
264                 hit = strcasestr(line, pattern);
265         else
266                 hit = strstr(line, pattern);
268         if (!hit) {
269                 match->rm_so = match->rm_eo = -1;
270                 return REG_NOMATCH;
271         }
272         else {
273                 match->rm_so = hit - line;
274                 match->rm_eo = match->rm_so + strlen(pattern);
275                 return 0;
276         }
279 static int strip_timestamp(char *bol, char **eol_p)
281         char *eol = *eol_p;
282         int ch;
284         while (bol < --eol) {
285                 if (*eol != '>')
286                         continue;
287                 *eol_p = ++eol;
288                 ch = *eol;
289                 *eol = '\0';
290                 return ch;
291         }
292         return 0;
295 static struct {
296         const char *field;
297         size_t len;
298 } header_field[] = {
299         { "author ", 7 },
300         { "committer ", 10 },
301 };
303 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
304                              enum grep_context ctx,
305                              regmatch_t *pmatch, int eflags)
307         int hit = 0;
308         int saved_ch = 0;
309         const char *start = bol;
311         if ((p->token != GREP_PATTERN) &&
312             ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
313                 return 0;
315         if (p->token == GREP_PATTERN_HEAD) {
316                 const char *field;
317                 size_t len;
318                 assert(p->field < ARRAY_SIZE(header_field));
319                 field = header_field[p->field].field;
320                 len = header_field[p->field].len;
321                 if (strncmp(bol, field, len))
322                         return 0;
323                 bol += len;
324                 saved_ch = strip_timestamp(bol, &eol);
325         }
327  again:
328         if (p->fixed)
329                 hit = !fixmatch(p->pattern, bol, p->ignore_case, pmatch);
330         else
331                 hit = !regexec(&p->regexp, bol, 1, pmatch, eflags);
333         if (hit && p->word_regexp) {
334                 if ((pmatch[0].rm_so < 0) ||
335                     (eol - bol) < pmatch[0].rm_so ||
336                     (pmatch[0].rm_eo < 0) ||
337                     (eol - bol) < pmatch[0].rm_eo)
338                         die("regexp returned nonsense");
340                 /* Match beginning must be either beginning of the
341                  * line, or at word boundary (i.e. the last char must
342                  * not be a word char).  Similarly, match end must be
343                  * either end of the line, or at word boundary
344                  * (i.e. the next char must not be a word char).
345                  */
346                 if ( ((pmatch[0].rm_so == 0) ||
347                       !word_char(bol[pmatch[0].rm_so-1])) &&
348                      ((pmatch[0].rm_eo == (eol-bol)) ||
349                       !word_char(bol[pmatch[0].rm_eo])) )
350                         ;
351                 else
352                         hit = 0;
354                 /* Words consist of at least one character. */
355                 if (pmatch->rm_so == pmatch->rm_eo)
356                         hit = 0;
358                 if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
359                         /* There could be more than one match on the
360                          * line, and the first match might not be
361                          * strict word match.  But later ones could be!
362                          * Forward to the next possible start, i.e. the
363                          * next position following a non-word char.
364                          */
365                         bol = pmatch[0].rm_so + bol + 1;
366                         while (word_char(bol[-1]) && bol < eol)
367                                 bol++;
368                         eflags |= REG_NOTBOL;
369                         if (bol < eol)
370                                 goto again;
371                 }
372         }
373         if (p->token == GREP_PATTERN_HEAD && saved_ch)
374                 *eol = saved_ch;
375         if (hit) {
376                 pmatch[0].rm_so += bol - start;
377                 pmatch[0].rm_eo += bol - start;
378         }
379         return hit;
382 static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
383                            enum grep_context ctx, int collect_hits)
385         int h = 0;
386         regmatch_t match;
388         if (!x)
389                 die("Not a valid grep expression");
390         switch (x->node) {
391         case GREP_NODE_ATOM:
392                 h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
393                 break;
394         case GREP_NODE_NOT:
395                 h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
396                 break;
397         case GREP_NODE_AND:
398                 if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
399                         return 0;
400                 h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
401                 break;
402         case GREP_NODE_OR:
403                 if (!collect_hits)
404                         return (match_expr_eval(x->u.binary.left,
405                                                 bol, eol, ctx, 0) ||
406                                 match_expr_eval(x->u.binary.right,
407                                                 bol, eol, ctx, 0));
408                 h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
409                 x->u.binary.left->hit |= h;
410                 h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
411                 break;
412         default:
413                 die("Unexpected node type (internal error) %d", x->node);
414         }
415         if (collect_hits)
416                 x->hit |= h;
417         return h;
420 static int match_expr(struct grep_opt *opt, char *bol, char *eol,
421                       enum grep_context ctx, int collect_hits)
423         struct grep_expr *x = opt->pattern_expression;
424         return match_expr_eval(x, bol, eol, ctx, collect_hits);
427 static int match_line(struct grep_opt *opt, char *bol, char *eol,
428                       enum grep_context ctx, int collect_hits)
430         struct grep_pat *p;
431         regmatch_t match;
433         if (opt->extended)
434                 return match_expr(opt, bol, eol, ctx, collect_hits);
436         /* we do not call with collect_hits without being extended */
437         for (p = opt->pattern_list; p; p = p->next) {
438                 if (match_one_pattern(p, bol, eol, ctx, &match, 0))
439                         return 1;
440         }
441         return 0;
444 static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
445                               enum grep_context ctx,
446                               regmatch_t *pmatch, int eflags)
448         regmatch_t match;
450         if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
451                 return 0;
452         if (match.rm_so < 0 || match.rm_eo < 0)
453                 return 0;
454         if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
455                 if (match.rm_so > pmatch->rm_so)
456                         return 1;
457                 if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
458                         return 1;
459         }
460         pmatch->rm_so = match.rm_so;
461         pmatch->rm_eo = match.rm_eo;
462         return 1;
465 static int next_match(struct grep_opt *opt, char *bol, char *eol,
466                       enum grep_context ctx, regmatch_t *pmatch, int eflags)
468         struct grep_pat *p;
469         int hit = 0;
471         pmatch->rm_so = pmatch->rm_eo = -1;
472         if (bol < eol) {
473                 for (p = opt->pattern_list; p; p = p->next) {
474                         switch (p->token) {
475                         case GREP_PATTERN: /* atom */
476                         case GREP_PATTERN_HEAD:
477                         case GREP_PATTERN_BODY:
478                                 hit |= match_next_pattern(p, bol, eol, ctx,
479                                                           pmatch, eflags);
480                                 break;
481                         default:
482                                 break;
483                         }
484                 }
485         }
486         return hit;
489 static void show_line(struct grep_opt *opt, char *bol, char *eol,
490                       const char *name, unsigned lno, char sign)
492         int rest = eol - bol;
494         if (opt->pre_context || opt->post_context) {
495                 if (opt->last_shown == 0) {
496                         if (opt->show_hunk_mark)
497                                 fputs("--\n", stdout);
498                         else
499                                 opt->show_hunk_mark = 1;
500                 } else if (lno > opt->last_shown + 1)
501                         fputs("--\n", stdout);
502         }
503         opt->last_shown = lno;
505         if (opt->null_following_name)
506                 sign = '\0';
507         if (opt->pathname)
508                 printf("%s%c", name, sign);
509         if (opt->linenum)
510                 printf("%d%c", lno, sign);
511         if (opt->color) {
512                 regmatch_t match;
513                 enum grep_context ctx = GREP_CONTEXT_BODY;
514                 int ch = *eol;
515                 int eflags = 0;
517                 *eol = '\0';
518                 while (next_match(opt, bol, eol, ctx, &match, eflags)) {
519                         if (match.rm_so == match.rm_eo)
520                                 break;
521                         printf("%.*s%s%.*s%s",
522                                (int)match.rm_so, bol,
523                                opt->color_match,
524                                (int)(match.rm_eo - match.rm_so), bol + match.rm_so,
525                                GIT_COLOR_RESET);
526                         bol += match.rm_eo;
527                         rest -= match.rm_eo;
528                         eflags = REG_NOTBOL;
529                 }
530                 *eol = ch;
531         }
532         printf("%.*s\n", rest, bol);
535 static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
537         xdemitconf_t *xecfg = opt->priv;
538         if (xecfg && xecfg->find_func) {
539                 char buf[1];
540                 return xecfg->find_func(bol, eol - bol, buf, 1,
541                                         xecfg->find_func_priv) >= 0;
542         }
544         if (bol == eol)
545                 return 0;
546         if (isalpha(*bol) || *bol == '_' || *bol == '$')
547                 return 1;
548         return 0;
551 static void show_funcname_line(struct grep_opt *opt, const char *name,
552                                char *buf, char *bol, unsigned lno)
554         while (bol > buf) {
555                 char *eol = --bol;
557                 while (bol > buf && bol[-1] != '\n')
558                         bol--;
559                 lno--;
561                 if (lno <= opt->last_shown)
562                         break;
564                 if (match_funcname(opt, bol, eol)) {
565                         show_line(opt, bol, eol, name, lno, '=');
566                         break;
567                 }
568         }
571 static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
572                              char *bol, unsigned lno)
574         unsigned cur = lno, from = 1, funcname_lno = 0;
575         int funcname_needed = opt->funcname;
577         if (opt->pre_context < lno)
578                 from = lno - opt->pre_context;
579         if (from <= opt->last_shown)
580                 from = opt->last_shown + 1;
582         /* Rewind. */
583         while (bol > buf && cur > from) {
584                 char *eol = --bol;
586                 while (bol > buf && bol[-1] != '\n')
587                         bol--;
588                 cur--;
589                 if (funcname_needed && match_funcname(opt, bol, eol)) {
590                         funcname_lno = cur;
591                         funcname_needed = 0;
592                 }
593         }
595         /* We need to look even further back to find a function signature. */
596         if (opt->funcname && funcname_needed)
597                 show_funcname_line(opt, name, buf, bol, cur);
599         /* Back forward. */
600         while (cur < lno) {
601                 char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
603                 while (*eol != '\n')
604                         eol++;
605                 show_line(opt, bol, eol, name, cur, sign);
606                 bol = eol + 1;
607                 cur++;
608         }
611 static int should_lookahead(struct grep_opt *opt)
613         struct grep_pat *p;
615         if (opt->extended)
616                 return 0; /* punt for too complex stuff */
617         if (opt->invert)
618                 return 0;
619         for (p = opt->pattern_list; p; p = p->next) {
620                 if (p->token != GREP_PATTERN)
621                         return 0; /* punt for "header only" and stuff */
622         }
623         return 1;
626 static int look_ahead(struct grep_opt *opt,
627                       unsigned long *left_p,
628                       unsigned *lno_p,
629                       char **bol_p)
631         unsigned lno = *lno_p;
632         char *bol = *bol_p;
633         struct grep_pat *p;
634         char *sp, *last_bol;
635         regoff_t earliest = -1;
637         for (p = opt->pattern_list; p; p = p->next) {
638                 int hit;
639                 regmatch_t m;
641                 if (p->fixed)
642                         hit = !fixmatch(p->pattern, bol, p->ignore_case, &m);
643                 else
644                         hit = !regexec(&p->regexp, bol, 1, &m, 0);
645                 if (!hit || m.rm_so < 0 || m.rm_eo < 0)
646                         continue;
647                 if (earliest < 0 || m.rm_so < earliest)
648                         earliest = m.rm_so;
649         }
651         if (earliest < 0) {
652                 *bol_p = bol + *left_p;
653                 *left_p = 0;
654                 return 1;
655         }
656         for (sp = bol + earliest; bol < sp && sp[-1] != '\n'; sp--)
657                 ; /* find the beginning of the line */
658         last_bol = sp;
660         for (sp = bol; sp < last_bol; sp++) {
661                 if (*sp == '\n')
662                         lno++;
663         }
664         *left_p -= last_bol - bol;
665         *bol_p = last_bol;
666         *lno_p = lno;
667         return 0;
670 static int grep_buffer_1(struct grep_opt *opt, const char *name,
671                          char *buf, unsigned long size, int collect_hits)
673         char *bol = buf;
674         unsigned long left = size;
675         unsigned lno = 1;
676         unsigned last_hit = 0;
677         int binary_match_only = 0;
678         unsigned count = 0;
679         int try_lookahead = 0;
680         enum grep_context ctx = GREP_CONTEXT_HEAD;
681         xdemitconf_t xecfg;
683         opt->last_shown = 0;
685         if (buffer_is_binary(buf, size)) {
686                 switch (opt->binary) {
687                 case GREP_BINARY_DEFAULT:
688                         binary_match_only = 1;
689                         break;
690                 case GREP_BINARY_NOMATCH:
691                         return 0; /* Assume unmatch */
692                         break;
693                 default:
694                         break;
695                 }
696         }
698         memset(&xecfg, 0, sizeof(xecfg));
699         if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
700             !opt->name_only && !binary_match_only && !collect_hits) {
701                 struct userdiff_driver *drv = userdiff_find_by_path(name);
702                 if (drv && drv->funcname.pattern) {
703                         const struct userdiff_funcname *pe = &drv->funcname;
704                         xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
705                         opt->priv = &xecfg;
706                 }
707         }
708         try_lookahead = should_lookahead(opt);
710         while (left) {
711                 char *eol, ch;
712                 int hit;
714                 /*
715                  * look_ahead() skips quicly to the line that possibly
716                  * has the next hit; don't call it if we need to do
717                  * something more than just skipping the current line
718                  * in response to an unmatch for the current line.  E.g.
719                  * inside a post-context window, we will show the current
720                  * line as a context around the previous hit when it
721                  * doesn't hit.
722                  */
723                 if (try_lookahead
724                     && !(last_hit
725                          && lno <= last_hit + opt->post_context)
726                     && look_ahead(opt, &left, &lno, &bol))
727                         break;
728                 eol = end_of_line(bol, &left);
729                 ch = *eol;
730                 *eol = 0;
732                 if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
733                         ctx = GREP_CONTEXT_BODY;
735                 hit = match_line(opt, bol, eol, ctx, collect_hits);
736                 *eol = ch;
738                 if (collect_hits)
739                         goto next_line;
741                 /* "grep -v -e foo -e bla" should list lines
742                  * that do not have either, so inversion should
743                  * be done outside.
744                  */
745                 if (opt->invert)
746                         hit = !hit;
747                 if (opt->unmatch_name_only) {
748                         if (hit)
749                                 return 0;
750                         goto next_line;
751                 }
752                 if (hit) {
753                         count++;
754                         if (opt->status_only)
755                                 return 1;
756                         if (binary_match_only) {
757                                 printf("Binary file %s matches\n", name);
758                                 return 1;
759                         }
760                         if (opt->name_only) {
761                                 show_name(opt, name);
762                                 return 1;
763                         }
764                         /* Hit at this line.  If we haven't shown the
765                          * pre-context lines, we would need to show them.
766                          * When asked to do "count", this still show
767                          * the context which is nonsense, but the user
768                          * deserves to get that ;-).
769                          */
770                         if (opt->pre_context)
771                                 show_pre_context(opt, name, buf, bol, lno);
772                         else if (opt->funcname)
773                                 show_funcname_line(opt, name, buf, bol, lno);
774                         if (!opt->count)
775                                 show_line(opt, bol, eol, name, lno, ':');
776                         last_hit = lno;
777                 }
778                 else if (last_hit &&
779                          lno <= last_hit + opt->post_context) {
780                         /* If the last hit is within the post context,
781                          * we need to show this line.
782                          */
783                         show_line(opt, bol, eol, name, lno, '-');
784                 }
786         next_line:
787                 bol = eol + 1;
788                 if (!left)
789                         break;
790                 left--;
791                 lno++;
792         }
794         if (collect_hits)
795                 return 0;
797         if (opt->status_only)
798                 return 0;
799         if (opt->unmatch_name_only) {
800                 /* We did not see any hit, so we want to show this */
801                 show_name(opt, name);
802                 return 1;
803         }
805         xdiff_clear_find_func(&xecfg);
806         opt->priv = NULL;
808         /* NEEDSWORK:
809          * The real "grep -c foo *.c" gives many "bar.c:0" lines,
810          * which feels mostly useless but sometimes useful.  Maybe
811          * make it another option?  For now suppress them.
812          */
813         if (opt->count && count)
814                 printf("%s%c%u\n", name,
815                        opt->null_following_name ? '\0' : ':', count);
816         return !!last_hit;
819 static void clr_hit_marker(struct grep_expr *x)
821         /* All-hit markers are meaningful only at the very top level
822          * OR node.
823          */
824         while (1) {
825                 x->hit = 0;
826                 if (x->node != GREP_NODE_OR)
827                         return;
828                 x->u.binary.left->hit = 0;
829                 x = x->u.binary.right;
830         }
833 static int chk_hit_marker(struct grep_expr *x)
835         /* Top level nodes have hit markers.  See if they all are hits */
836         while (1) {
837                 if (x->node != GREP_NODE_OR)
838                         return x->hit;
839                 if (!x->u.binary.left->hit)
840                         return 0;
841                 x = x->u.binary.right;
842         }
845 int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size)
847         /*
848          * we do not have to do the two-pass grep when we do not check
849          * buffer-wide "all-match".
850          */
851         if (!opt->all_match)
852                 return grep_buffer_1(opt, name, buf, size, 0);
854         /* Otherwise the toplevel "or" terms hit a bit differently.
855          * We first clear hit markers from them.
856          */
857         clr_hit_marker(opt->pattern_expression);
858         grep_buffer_1(opt, name, buf, size, 1);
860         if (!chk_hit_marker(opt->pattern_expression))
861                 return 0;
863         return grep_buffer_1(opt, name, buf, size, 0);