grep.con commit Merge branch 'rs/work-around-grep-opt-insanity' (ad7ace7)
   1#include "cache.h"
   2#include "grep.h"
   3#include "userdiff.h"
   4#include "xdiff-interface.h"
   5
   6void 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}
  18
  19void 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}
  31
  32static int is_fixed(const char *s)
  33{
  34        while (*s && !is_regex_special(*s))
  35                s++;
  36        return !*s;
  37}
  38
  39static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
  40{
  41        int err;
  42
  43        p->word_regexp = opt->word_regexp;
  44        p->ignore_case = opt->ignore_case;
  45
  46        if (opt->fixed || is_fixed(p->pattern))
  47                p->fixed = 1;
  48        if (opt->regflags & REG_ICASE)
  49                p->fixed = 0;
  50        if (p->fixed)
  51                return;
  52
  53        err = regcomp(&p->regexp, p->pattern, opt->regflags);
  54        if (err) {
  55                char errbuf[1024];
  56                char where[1024];
  57                if (p->no)
  58                        sprintf(where, "In '%s' at %d, ",
  59                                p->origin, p->no);
  60                else if (p->origin)
  61                        sprintf(where, "%s, ", p->origin);
  62                else
  63                        where[0] = 0;
  64                regerror(err, &p->regexp, errbuf, 1024);
  65                regfree(&p->regexp);
  66                die("%s'%s': %s", where, p->pattern, errbuf);
  67        }
  68}
  69
  70static struct grep_expr *compile_pattern_or(struct grep_pat **);
  71static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
  72{
  73        struct grep_pat *p;
  74        struct grep_expr *x;
  75
  76        p = *list;
  77        if (!p)
  78                return NULL;
  79        switch (p->token) {
  80        case GREP_PATTERN: /* atom */
  81        case GREP_PATTERN_HEAD:
  82        case GREP_PATTERN_BODY:
  83                x = xcalloc(1, sizeof (struct grep_expr));
  84                x->node = GREP_NODE_ATOM;
  85                x->u.atom = p;
  86                *list = p->next;
  87                return x;
  88        case GREP_OPEN_PAREN:
  89                *list = p->next;
  90                x = compile_pattern_or(list);
  91                if (!*list || (*list)->token != GREP_CLOSE_PAREN)
  92                        die("unmatched parenthesis");
  93                *list = (*list)->next;
  94                return x;
  95        default:
  96                return NULL;
  97        }
  98}
  99
 100static struct grep_expr *compile_pattern_not(struct grep_pat **list)
 101{
 102        struct grep_pat *p;
 103        struct grep_expr *x;
 104
 105        p = *list;
 106        if (!p)
 107                return NULL;
 108        switch (p->token) {
 109        case GREP_NOT:
 110                if (!p->next)
 111                        die("--not not followed by pattern expression");
 112                *list = p->next;
 113                x = xcalloc(1, sizeof (struct grep_expr));
 114                x->node = GREP_NODE_NOT;
 115                x->u.unary = compile_pattern_not(list);
 116                if (!x->u.unary)
 117                        die("--not followed by non pattern expression");
 118                return x;
 119        default:
 120                return compile_pattern_atom(list);
 121        }
 122}
 123
 124static struct grep_expr *compile_pattern_and(struct grep_pat **list)
 125{
 126        struct grep_pat *p;
 127        struct grep_expr *x, *y, *z;
 128
 129        x = compile_pattern_not(list);
 130        p = *list;
 131        if (p && p->token == GREP_AND) {
 132                if (!p->next)
 133                        die("--and not followed by pattern expression");
 134                *list = p->next;
 135                y = compile_pattern_and(list);
 136                if (!y)
 137                        die("--and not followed by pattern expression");
 138                z = xcalloc(1, sizeof (struct grep_expr));
 139                z->node = GREP_NODE_AND;
 140                z->u.binary.left = x;
 141                z->u.binary.right = y;
 142                return z;
 143        }
 144        return x;
 145}
 146
 147static struct grep_expr *compile_pattern_or(struct grep_pat **list)
 148{
 149        struct grep_pat *p;
 150        struct grep_expr *x, *y, *z;
 151
 152        x = compile_pattern_and(list);
 153        p = *list;
 154        if (x && p && p->token != GREP_CLOSE_PAREN) {
 155                y = compile_pattern_or(list);
 156                if (!y)
 157                        die("not a pattern expression %s", p->pattern);
 158                z = xcalloc(1, sizeof (struct grep_expr));
 159                z->node = GREP_NODE_OR;
 160                z->u.binary.left = x;
 161                z->u.binary.right = y;
 162                return z;
 163        }
 164        return x;
 165}
 166
 167static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
 168{
 169        return compile_pattern_or(list);
 170}
 171
 172void compile_grep_patterns(struct grep_opt *opt)
 173{
 174        struct grep_pat *p;
 175
 176        if (opt->all_match)
 177                opt->extended = 1;
 178
 179        for (p = opt->pattern_list; p; p = p->next) {
 180                switch (p->token) {
 181                case GREP_PATTERN: /* atom */
 182                case GREP_PATTERN_HEAD:
 183                case GREP_PATTERN_BODY:
 184                        compile_regexp(p, opt);
 185                        break;
 186                default:
 187                        opt->extended = 1;
 188                        break;
 189                }
 190        }
 191
 192        if (!opt->extended)
 193                return;
 194
 195        /* Then bundle them up in an expression.
 196         * A classic recursive descent parser would do.
 197         */
 198        p = opt->pattern_list;
 199        if (p)
 200                opt->pattern_expression = compile_pattern_expr(&p);
 201        if (p)
 202                die("incomplete pattern expression: %s", p->pattern);
 203}
 204
 205static void free_pattern_expr(struct grep_expr *x)
 206{
 207        switch (x->node) {
 208        case GREP_NODE_ATOM:
 209                break;
 210        case GREP_NODE_NOT:
 211                free_pattern_expr(x->u.unary);
 212                break;
 213        case GREP_NODE_AND:
 214        case GREP_NODE_OR:
 215                free_pattern_expr(x->u.binary.left);
 216                free_pattern_expr(x->u.binary.right);
 217                break;
 218        }
 219        free(x);
 220}
 221
 222void free_grep_patterns(struct grep_opt *opt)
 223{
 224        struct grep_pat *p, *n;
 225
 226        for (p = opt->pattern_list; p; p = n) {
 227                n = p->next;
 228                switch (p->token) {
 229                case GREP_PATTERN: /* atom */
 230                case GREP_PATTERN_HEAD:
 231                case GREP_PATTERN_BODY:
 232                        regfree(&p->regexp);
 233                        break;
 234                default:
 235                        break;
 236                }
 237                free(p);
 238        }
 239
 240        if (!opt->extended)
 241                return;
 242        free_pattern_expr(opt->pattern_expression);
 243}
 244
 245static char *end_of_line(char *cp, unsigned long *left)
 246{
 247        unsigned long l = *left;
 248        while (l && *cp != '\n') {
 249                l--;
 250                cp++;
 251        }
 252        *left = l;
 253        return cp;
 254}
 255
 256static int word_char(char ch)
 257{
 258        return isalnum(ch) || ch == '_';
 259}
 260
 261static void show_name(struct grep_opt *opt, const char *name)
 262{
 263        printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
 264}
 265
 266
 267static int fixmatch(const char *pattern, char *line, int ignore_case, regmatch_t *match)
 268{
 269        char *hit;
 270        if (ignore_case)
 271                hit = strcasestr(line, pattern);
 272        else
 273                hit = strstr(line, pattern);
 274
 275        if (!hit) {
 276                match->rm_so = match->rm_eo = -1;
 277                return REG_NOMATCH;
 278        }
 279        else {
 280                match->rm_so = hit - line;
 281                match->rm_eo = match->rm_so + strlen(pattern);
 282                return 0;
 283        }
 284}
 285
 286static int strip_timestamp(char *bol, char **eol_p)
 287{
 288        char *eol = *eol_p;
 289        int ch;
 290
 291        while (bol < --eol) {
 292                if (*eol != '>')
 293                        continue;
 294                *eol_p = ++eol;
 295                ch = *eol;
 296                *eol = '\0';
 297                return ch;
 298        }
 299        return 0;
 300}
 301
 302static struct {
 303        const char *field;
 304        size_t len;
 305} header_field[] = {
 306        { "author ", 7 },
 307        { "committer ", 10 },
 308};
 309
 310static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 311                             enum grep_context ctx,
 312                             regmatch_t *pmatch, int eflags)
 313{
 314        int hit = 0;
 315        int saved_ch = 0;
 316        const char *start = bol;
 317
 318        if ((p->token != GREP_PATTERN) &&
 319            ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
 320                return 0;
 321
 322        if (p->token == GREP_PATTERN_HEAD) {
 323                const char *field;
 324                size_t len;
 325                assert(p->field < ARRAY_SIZE(header_field));
 326                field = header_field[p->field].field;
 327                len = header_field[p->field].len;
 328                if (strncmp(bol, field, len))
 329                        return 0;
 330                bol += len;
 331                saved_ch = strip_timestamp(bol, &eol);
 332        }
 333
 334 again:
 335        if (p->fixed)
 336                hit = !fixmatch(p->pattern, bol, p->ignore_case, pmatch);
 337        else
 338                hit = !regexec(&p->regexp, bol, 1, pmatch, eflags);
 339
 340        if (hit && p->word_regexp) {
 341                if ((pmatch[0].rm_so < 0) ||
 342                    (eol - bol) < pmatch[0].rm_so ||
 343                    (pmatch[0].rm_eo < 0) ||
 344                    (eol - bol) < pmatch[0].rm_eo)
 345                        die("regexp returned nonsense");
 346
 347                /* Match beginning must be either beginning of the
 348                 * line, or at word boundary (i.e. the last char must
 349                 * not be a word char).  Similarly, match end must be
 350                 * either end of the line, or at word boundary
 351                 * (i.e. the next char must not be a word char).
 352                 */
 353                if ( ((pmatch[0].rm_so == 0) ||
 354                      !word_char(bol[pmatch[0].rm_so-1])) &&
 355                     ((pmatch[0].rm_eo == (eol-bol)) ||
 356                      !word_char(bol[pmatch[0].rm_eo])) )
 357                        ;
 358                else
 359                        hit = 0;
 360
 361                /* Words consist of at least one character. */
 362                if (pmatch->rm_so == pmatch->rm_eo)
 363                        hit = 0;
 364
 365                if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
 366                        /* There could be more than one match on the
 367                         * line, and the first match might not be
 368                         * strict word match.  But later ones could be!
 369                         * Forward to the next possible start, i.e. the
 370                         * next position following a non-word char.
 371                         */
 372                        bol = pmatch[0].rm_so + bol + 1;
 373                        while (word_char(bol[-1]) && bol < eol)
 374                                bol++;
 375                        eflags |= REG_NOTBOL;
 376                        if (bol < eol)
 377                                goto again;
 378                }
 379        }
 380        if (p->token == GREP_PATTERN_HEAD && saved_ch)
 381                *eol = saved_ch;
 382        if (hit) {
 383                pmatch[0].rm_so += bol - start;
 384                pmatch[0].rm_eo += bol - start;
 385        }
 386        return hit;
 387}
 388
 389static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
 390                           enum grep_context ctx, int collect_hits)
 391{
 392        int h = 0;
 393        regmatch_t match;
 394
 395        if (!x)
 396                die("Not a valid grep expression");
 397        switch (x->node) {
 398        case GREP_NODE_ATOM:
 399                h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
 400                break;
 401        case GREP_NODE_NOT:
 402                h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
 403                break;
 404        case GREP_NODE_AND:
 405                if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
 406                        return 0;
 407                h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
 408                break;
 409        case GREP_NODE_OR:
 410                if (!collect_hits)
 411                        return (match_expr_eval(x->u.binary.left,
 412                                                bol, eol, ctx, 0) ||
 413                                match_expr_eval(x->u.binary.right,
 414                                                bol, eol, ctx, 0));
 415                h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
 416                x->u.binary.left->hit |= h;
 417                h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
 418                break;
 419        default:
 420                die("Unexpected node type (internal error) %d", x->node);
 421        }
 422        if (collect_hits)
 423                x->hit |= h;
 424        return h;
 425}
 426
 427static int match_expr(struct grep_opt *opt, char *bol, char *eol,
 428                      enum grep_context ctx, int collect_hits)
 429{
 430        struct grep_expr *x = opt->pattern_expression;
 431        return match_expr_eval(x, bol, eol, ctx, collect_hits);
 432}
 433
 434static int match_line(struct grep_opt *opt, char *bol, char *eol,
 435                      enum grep_context ctx, int collect_hits)
 436{
 437        struct grep_pat *p;
 438        regmatch_t match;
 439
 440        if (opt->extended)
 441                return match_expr(opt, bol, eol, ctx, collect_hits);
 442
 443        /* we do not call with collect_hits without being extended */
 444        for (p = opt->pattern_list; p; p = p->next) {
 445                if (match_one_pattern(p, bol, eol, ctx, &match, 0))
 446                        return 1;
 447        }
 448        return 0;
 449}
 450
 451static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
 452                              enum grep_context ctx,
 453                              regmatch_t *pmatch, int eflags)
 454{
 455        regmatch_t match;
 456
 457        if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
 458                return 0;
 459        if (match.rm_so < 0 || match.rm_eo < 0)
 460                return 0;
 461        if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
 462                if (match.rm_so > pmatch->rm_so)
 463                        return 1;
 464                if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
 465                        return 1;
 466        }
 467        pmatch->rm_so = match.rm_so;
 468        pmatch->rm_eo = match.rm_eo;
 469        return 1;
 470}
 471
 472static int next_match(struct grep_opt *opt, char *bol, char *eol,
 473                      enum grep_context ctx, regmatch_t *pmatch, int eflags)
 474{
 475        struct grep_pat *p;
 476        int hit = 0;
 477
 478        pmatch->rm_so = pmatch->rm_eo = -1;
 479        if (bol < eol) {
 480                for (p = opt->pattern_list; p; p = p->next) {
 481                        switch (p->token) {
 482                        case GREP_PATTERN: /* atom */
 483                        case GREP_PATTERN_HEAD:
 484                        case GREP_PATTERN_BODY:
 485                                hit |= match_next_pattern(p, bol, eol, ctx,
 486                                                          pmatch, eflags);
 487                                break;
 488                        default:
 489                                break;
 490                        }
 491                }
 492        }
 493        return hit;
 494}
 495
 496static void show_line(struct grep_opt *opt, char *bol, char *eol,
 497                      const char *name, unsigned lno, char sign)
 498{
 499        int rest = eol - bol;
 500
 501        if (opt->pre_context || opt->post_context) {
 502                if (opt->last_shown == 0) {
 503                        if (opt->show_hunk_mark)
 504                                fputs("--\n", stdout);
 505                        else
 506                                opt->show_hunk_mark = 1;
 507                } else if (lno > opt->last_shown + 1)
 508                        fputs("--\n", stdout);
 509        }
 510        opt->last_shown = lno;
 511
 512        if (opt->null_following_name)
 513                sign = '\0';
 514        if (opt->pathname)
 515                printf("%s%c", name, sign);
 516        if (opt->linenum)
 517                printf("%d%c", lno, sign);
 518        if (opt->color) {
 519                regmatch_t match;
 520                enum grep_context ctx = GREP_CONTEXT_BODY;
 521                int ch = *eol;
 522                int eflags = 0;
 523
 524                *eol = '\0';
 525                while (next_match(opt, bol, eol, ctx, &match, eflags)) {
 526                        if (match.rm_so == match.rm_eo)
 527                                break;
 528                        printf("%.*s%s%.*s%s",
 529                               (int)match.rm_so, bol,
 530                               opt->color_match,
 531                               (int)(match.rm_eo - match.rm_so), bol + match.rm_so,
 532                               GIT_COLOR_RESET);
 533                        bol += match.rm_eo;
 534                        rest -= match.rm_eo;
 535                        eflags = REG_NOTBOL;
 536                }
 537                *eol = ch;
 538        }
 539        printf("%.*s\n", rest, bol);
 540}
 541
 542static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
 543{
 544        xdemitconf_t *xecfg = opt->priv;
 545        if (xecfg && xecfg->find_func) {
 546                char buf[1];
 547                return xecfg->find_func(bol, eol - bol, buf, 1,
 548                                        xecfg->find_func_priv) >= 0;
 549        }
 550
 551        if (bol == eol)
 552                return 0;
 553        if (isalpha(*bol) || *bol == '_' || *bol == '$')
 554                return 1;
 555        return 0;
 556}
 557
 558static void show_funcname_line(struct grep_opt *opt, const char *name,
 559                               char *buf, char *bol, unsigned lno)
 560{
 561        while (bol > buf) {
 562                char *eol = --bol;
 563
 564                while (bol > buf && bol[-1] != '\n')
 565                        bol--;
 566                lno--;
 567
 568                if (lno <= opt->last_shown)
 569                        break;
 570
 571                if (match_funcname(opt, bol, eol)) {
 572                        show_line(opt, bol, eol, name, lno, '=');
 573                        break;
 574                }
 575        }
 576}
 577
 578static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
 579                             char *bol, unsigned lno)
 580{
 581        unsigned cur = lno, from = 1, funcname_lno = 0;
 582        int funcname_needed = opt->funcname;
 583
 584        if (opt->pre_context < lno)
 585                from = lno - opt->pre_context;
 586        if (from <= opt->last_shown)
 587                from = opt->last_shown + 1;
 588
 589        /* Rewind. */
 590        while (bol > buf && cur > from) {
 591                char *eol = --bol;
 592
 593                while (bol > buf && bol[-1] != '\n')
 594                        bol--;
 595                cur--;
 596                if (funcname_needed && match_funcname(opt, bol, eol)) {
 597                        funcname_lno = cur;
 598                        funcname_needed = 0;
 599                }
 600        }
 601
 602        /* We need to look even further back to find a function signature. */
 603        if (opt->funcname && funcname_needed)
 604                show_funcname_line(opt, name, buf, bol, cur);
 605
 606        /* Back forward. */
 607        while (cur < lno) {
 608                char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
 609
 610                while (*eol != '\n')
 611                        eol++;
 612                show_line(opt, bol, eol, name, cur, sign);
 613                bol = eol + 1;
 614                cur++;
 615        }
 616}
 617
 618static int grep_buffer_1(struct grep_opt *opt, const char *name,
 619                         char *buf, unsigned long size, int collect_hits)
 620{
 621        char *bol = buf;
 622        unsigned long left = size;
 623        unsigned lno = 1;
 624        unsigned last_hit = 0;
 625        int binary_match_only = 0;
 626        unsigned count = 0;
 627        enum grep_context ctx = GREP_CONTEXT_HEAD;
 628        xdemitconf_t xecfg;
 629
 630        opt->last_shown = 0;
 631
 632        if (buffer_is_binary(buf, size)) {
 633                switch (opt->binary) {
 634                case GREP_BINARY_DEFAULT:
 635                        binary_match_only = 1;
 636                        break;
 637                case GREP_BINARY_NOMATCH:
 638                        return 0; /* Assume unmatch */
 639                        break;
 640                default:
 641                        break;
 642                }
 643        }
 644
 645        memset(&xecfg, 0, sizeof(xecfg));
 646        if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
 647            !opt->name_only && !binary_match_only && !collect_hits) {
 648                struct userdiff_driver *drv = userdiff_find_by_path(name);
 649                if (drv && drv->funcname.pattern) {
 650                        const struct userdiff_funcname *pe = &drv->funcname;
 651                        xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
 652                        opt->priv = &xecfg;
 653                }
 654        }
 655
 656        while (left) {
 657                char *eol, ch;
 658                int hit;
 659
 660                eol = end_of_line(bol, &left);
 661                ch = *eol;
 662                *eol = 0;
 663
 664                if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
 665                        ctx = GREP_CONTEXT_BODY;
 666
 667                hit = match_line(opt, bol, eol, ctx, collect_hits);
 668                *eol = ch;
 669
 670                if (collect_hits)
 671                        goto next_line;
 672
 673                /* "grep -v -e foo -e bla" should list lines
 674                 * that do not have either, so inversion should
 675                 * be done outside.
 676                 */
 677                if (opt->invert)
 678                        hit = !hit;
 679                if (opt->unmatch_name_only) {
 680                        if (hit)
 681                                return 0;
 682                        goto next_line;
 683                }
 684                if (hit) {
 685                        count++;
 686                        if (opt->status_only)
 687                                return 1;
 688                        if (binary_match_only) {
 689                                printf("Binary file %s matches\n", name);
 690                                return 1;
 691                        }
 692                        if (opt->name_only) {
 693                                show_name(opt, name);
 694                                return 1;
 695                        }
 696                        /* Hit at this line.  If we haven't shown the
 697                         * pre-context lines, we would need to show them.
 698                         * When asked to do "count", this still show
 699                         * the context which is nonsense, but the user
 700                         * deserves to get that ;-).
 701                         */
 702                        if (opt->pre_context)
 703                                show_pre_context(opt, name, buf, bol, lno);
 704                        else if (opt->funcname)
 705                                show_funcname_line(opt, name, buf, bol, lno);
 706                        if (!opt->count)
 707                                show_line(opt, bol, eol, name, lno, ':');
 708                        last_hit = lno;
 709                }
 710                else if (last_hit &&
 711                         lno <= last_hit + opt->post_context) {
 712                        /* If the last hit is within the post context,
 713                         * we need to show this line.
 714                         */
 715                        show_line(opt, bol, eol, name, lno, '-');
 716                }
 717
 718        next_line:
 719                bol = eol + 1;
 720                if (!left)
 721                        break;
 722                left--;
 723                lno++;
 724        }
 725
 726        if (collect_hits)
 727                return 0;
 728
 729        if (opt->status_only)
 730                return 0;
 731        if (opt->unmatch_name_only) {
 732                /* We did not see any hit, so we want to show this */
 733                show_name(opt, name);
 734                return 1;
 735        }
 736
 737        xdiff_clear_find_func(&xecfg);
 738        opt->priv = NULL;
 739
 740        /* NEEDSWORK:
 741         * The real "grep -c foo *.c" gives many "bar.c:0" lines,
 742         * which feels mostly useless but sometimes useful.  Maybe
 743         * make it another option?  For now suppress them.
 744         */
 745        if (opt->count && count)
 746                printf("%s%c%u\n", name,
 747                       opt->null_following_name ? '\0' : ':', count);
 748        return !!last_hit;
 749}
 750
 751static void clr_hit_marker(struct grep_expr *x)
 752{
 753        /* All-hit markers are meaningful only at the very top level
 754         * OR node.
 755         */
 756        while (1) {
 757                x->hit = 0;
 758                if (x->node != GREP_NODE_OR)
 759                        return;
 760                x->u.binary.left->hit = 0;
 761                x = x->u.binary.right;
 762        }
 763}
 764
 765static int chk_hit_marker(struct grep_expr *x)
 766{
 767        /* Top level nodes have hit markers.  See if they all are hits */
 768        while (1) {
 769                if (x->node != GREP_NODE_OR)
 770                        return x->hit;
 771                if (!x->u.binary.left->hit)
 772                        return 0;
 773                x = x->u.binary.right;
 774        }
 775}
 776
 777int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size)
 778{
 779        /*
 780         * we do not have to do the two-pass grep when we do not check
 781         * buffer-wide "all-match".
 782         */
 783        if (!opt->all_match)
 784                return grep_buffer_1(opt, name, buf, size, 0);
 785
 786        /* Otherwise the toplevel "or" terms hit a bit differently.
 787         * We first clear hit markers from them.
 788         */
 789        clr_hit_marker(opt->pattern_expression);
 790        grep_buffer_1(opt, name, buf, size, 1);
 791
 792        if (!chk_hit_marker(opt->pattern_expression))
 793                return 0;
 794
 795        return grep_buffer_1(opt, name, buf, size, 0);
 796}