grep: factor out do_append_grep_pat()
[git] / grep.c
1 #include "cache.h"
2 #include "grep.h"
3 #include "userdiff.h"
4 #include "xdiff-interface.h"
5
6 static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
7                                         const char *origin, int no,
8                                         enum grep_pat_token t,
9                                         enum grep_header_field field)
10 {
11         struct grep_pat *p = xcalloc(1, sizeof(*p));
12         p->pattern = pat;
13         p->patternlen = patlen;
14         p->origin = origin;
15         p->no = no;
16         p->token = t;
17         p->field = field;
18         return p;
19 }
20
21 static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
22 {
23         **tail = p;
24         *tail = &p->next;
25         p->next = NULL;
26 }
27
28 void append_header_grep_pattern(struct grep_opt *opt,
29                                 enum grep_header_field field, const char *pat)
30 {
31         struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
32                                              GREP_PATTERN_HEAD, field);
33         do_append_grep_pat(&opt->header_tail, p);
34 }
35
36 void append_grep_pattern(struct grep_opt *opt, const char *pat,
37                          const char *origin, int no, enum grep_pat_token t)
38 {
39         append_grep_pat(opt, pat, strlen(pat), origin, no, t);
40 }
41
42 void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
43                      const char *origin, int no, enum grep_pat_token t)
44 {
45         struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, 0);
46         do_append_grep_pat(&opt->pattern_tail, p);
47 }
48
49 struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
50 {
51         struct grep_pat *pat;
52         struct grep_opt *ret = xmalloc(sizeof(struct grep_opt));
53         *ret = *opt;
54
55         ret->pattern_list = NULL;
56         ret->pattern_tail = &ret->pattern_list;
57
58         for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
59         {
60                 if(pat->token == GREP_PATTERN_HEAD)
61                         append_header_grep_pattern(ret, pat->field,
62                                                    pat->pattern);
63                 else
64                         append_grep_pat(ret, pat->pattern, pat->patternlen,
65                                         pat->origin, pat->no, pat->token);
66         }
67
68         return ret;
69 }
70
71 static NORETURN void compile_regexp_failed(const struct grep_pat *p,
72                 const char *error)
73 {
74         char where[1024];
75
76         if (p->no)
77                 sprintf(where, "In '%s' at %d, ", p->origin, p->no);
78         else if (p->origin)
79                 sprintf(where, "%s, ", p->origin);
80         else
81                 where[0] = 0;
82
83         die("%s'%s': %s", where, p->pattern, error);
84 }
85
86 #ifdef USE_LIBPCRE
87 static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
88 {
89         const char *error;
90         int erroffset;
91         int options = 0;
92
93         if (opt->ignore_case)
94                 options |= PCRE_CASELESS;
95
96         p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
97                         NULL);
98         if (!p->pcre_regexp)
99                 compile_regexp_failed(p, error);
100
101         p->pcre_extra_info = pcre_study(p->pcre_regexp, 0, &error);
102         if (!p->pcre_extra_info && error)
103                 die("%s", error);
104 }
105
106 static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
107                 regmatch_t *match, int eflags)
108 {
109         int ovector[30], ret, flags = 0;
110
111         if (eflags & REG_NOTBOL)
112                 flags |= PCRE_NOTBOL;
113
114         ret = pcre_exec(p->pcre_regexp, p->pcre_extra_info, line, eol - line,
115                         0, flags, ovector, ARRAY_SIZE(ovector));
116         if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
117                 die("pcre_exec failed with error code %d", ret);
118         if (ret > 0) {
119                 ret = 0;
120                 match->rm_so = ovector[0];
121                 match->rm_eo = ovector[1];
122         }
123
124         return ret;
125 }
126
127 static void free_pcre_regexp(struct grep_pat *p)
128 {
129         pcre_free(p->pcre_regexp);
130         pcre_free(p->pcre_extra_info);
131 }
132 #else /* !USE_LIBPCRE */
133 static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
134 {
135         die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
136 }
137
138 static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
139                 regmatch_t *match, int eflags)
140 {
141         return 1;
142 }
143
144 static void free_pcre_regexp(struct grep_pat *p)
145 {
146 }
147 #endif /* !USE_LIBPCRE */
148
149 static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
150 {
151         int err;
152
153         p->word_regexp = opt->word_regexp;
154         p->ignore_case = opt->ignore_case;
155         p->fixed = opt->fixed;
156
157         if (p->fixed)
158                 return;
159
160         if (opt->pcre) {
161                 compile_pcre_regexp(p, opt);
162                 return;
163         }
164
165         err = regcomp(&p->regexp, p->pattern, opt->regflags);
166         if (err) {
167                 char errbuf[1024];
168                 regerror(err, &p->regexp, errbuf, 1024);
169                 regfree(&p->regexp);
170                 compile_regexp_failed(p, errbuf);
171         }
172 }
173
174 static struct grep_expr *compile_pattern_or(struct grep_pat **);
175 static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
176 {
177         struct grep_pat *p;
178         struct grep_expr *x;
179
180         p = *list;
181         if (!p)
182                 return NULL;
183         switch (p->token) {
184         case GREP_PATTERN: /* atom */
185         case GREP_PATTERN_HEAD:
186         case GREP_PATTERN_BODY:
187                 x = xcalloc(1, sizeof (struct grep_expr));
188                 x->node = GREP_NODE_ATOM;
189                 x->u.atom = p;
190                 *list = p->next;
191                 return x;
192         case GREP_OPEN_PAREN:
193                 *list = p->next;
194                 x = compile_pattern_or(list);
195                 if (!*list || (*list)->token != GREP_CLOSE_PAREN)
196                         die("unmatched parenthesis");
197                 *list = (*list)->next;
198                 return x;
199         default:
200                 return NULL;
201         }
202 }
203
204 static struct grep_expr *compile_pattern_not(struct grep_pat **list)
205 {
206         struct grep_pat *p;
207         struct grep_expr *x;
208
209         p = *list;
210         if (!p)
211                 return NULL;
212         switch (p->token) {
213         case GREP_NOT:
214                 if (!p->next)
215                         die("--not not followed by pattern expression");
216                 *list = p->next;
217                 x = xcalloc(1, sizeof (struct grep_expr));
218                 x->node = GREP_NODE_NOT;
219                 x->u.unary = compile_pattern_not(list);
220                 if (!x->u.unary)
221                         die("--not followed by non pattern expression");
222                 return x;
223         default:
224                 return compile_pattern_atom(list);
225         }
226 }
227
228 static struct grep_expr *compile_pattern_and(struct grep_pat **list)
229 {
230         struct grep_pat *p;
231         struct grep_expr *x, *y, *z;
232
233         x = compile_pattern_not(list);
234         p = *list;
235         if (p && p->token == GREP_AND) {
236                 if (!p->next)
237                         die("--and not followed by pattern expression");
238                 *list = p->next;
239                 y = compile_pattern_and(list);
240                 if (!y)
241                         die("--and not followed by pattern expression");
242                 z = xcalloc(1, sizeof (struct grep_expr));
243                 z->node = GREP_NODE_AND;
244                 z->u.binary.left = x;
245                 z->u.binary.right = y;
246                 return z;
247         }
248         return x;
249 }
250
251 static struct grep_expr *compile_pattern_or(struct grep_pat **list)
252 {
253         struct grep_pat *p;
254         struct grep_expr *x, *y, *z;
255
256         x = compile_pattern_and(list);
257         p = *list;
258         if (x && p && p->token != GREP_CLOSE_PAREN) {
259                 y = compile_pattern_or(list);
260                 if (!y)
261                         die("not a pattern expression %s", p->pattern);
262                 z = xcalloc(1, sizeof (struct grep_expr));
263                 z->node = GREP_NODE_OR;
264                 z->u.binary.left = x;
265                 z->u.binary.right = y;
266                 return z;
267         }
268         return x;
269 }
270
271 static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
272 {
273         return compile_pattern_or(list);
274 }
275
276 static struct grep_expr *grep_true_expr(void)
277 {
278         struct grep_expr *z = xcalloc(1, sizeof(*z));
279         z->node = GREP_NODE_TRUE;
280         return z;
281 }
282
283 static struct grep_expr *grep_or_expr(struct grep_expr *left, struct grep_expr *right)
284 {
285         struct grep_expr *z = xcalloc(1, sizeof(*z));
286         z->node = GREP_NODE_OR;
287         z->u.binary.left = left;
288         z->u.binary.right = right;
289         return z;
290 }
291
292 static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
293 {
294         struct grep_pat *p;
295         struct grep_expr *header_expr;
296         struct grep_expr *(header_group[GREP_HEADER_FIELD_MAX]);
297         enum grep_header_field fld;
298
299         if (!opt->header_list)
300                 return NULL;
301         p = opt->header_list;
302         for (p = opt->header_list; p; p = p->next) {
303                 if (p->token != GREP_PATTERN_HEAD)
304                         die("bug: a non-header pattern in grep header list.");
305                 if (p->field < 0 || GREP_HEADER_FIELD_MAX <= p->field)
306                         die("bug: unknown header field %d", p->field);
307                 compile_regexp(p, opt);
308         }
309
310         for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++)
311                 header_group[fld] = NULL;
312
313         for (p = opt->header_list; p; p = p->next) {
314                 struct grep_expr *h;
315                 struct grep_pat *pp = p;
316
317                 h = compile_pattern_atom(&pp);
318                 if (!h || pp != p->next)
319                         die("bug: malformed header expr");
320                 if (!header_group[p->field]) {
321                         header_group[p->field] = h;
322                         continue;
323                 }
324                 header_group[p->field] = grep_or_expr(h, header_group[p->field]);
325         }
326
327         header_expr = NULL;
328
329         for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++) {
330                 if (!header_group[fld])
331                         continue;
332                 if (!header_expr)
333                         header_expr = grep_true_expr();
334                 header_expr = grep_or_expr(header_group[fld], header_expr);
335         }
336         return header_expr;
337 }
338
339 void compile_grep_patterns(struct grep_opt *opt)
340 {
341         struct grep_pat *p;
342         struct grep_expr *header_expr = prep_header_patterns(opt);
343
344         for (p = opt->pattern_list; p; p = p->next) {
345                 switch (p->token) {
346                 case GREP_PATTERN: /* atom */
347                 case GREP_PATTERN_HEAD:
348                 case GREP_PATTERN_BODY:
349                         compile_regexp(p, opt);
350                         break;
351                 default:
352                         opt->extended = 1;
353                         break;
354                 }
355         }
356
357         if (opt->all_match || header_expr)
358                 opt->extended = 1;
359         else if (!opt->extended)
360                 return;
361
362         p = opt->pattern_list;
363         if (p)
364                 opt->pattern_expression = compile_pattern_expr(&p);
365         if (p)
366                 die("incomplete pattern expression: %s", p->pattern);
367
368         if (!header_expr)
369                 return;
370
371         if (!opt->pattern_expression)
372                 opt->pattern_expression = header_expr;
373         else
374                 opt->pattern_expression = grep_or_expr(opt->pattern_expression,
375                                                        header_expr);
376         opt->all_match = 1;
377 }
378
379 static void free_pattern_expr(struct grep_expr *x)
380 {
381         switch (x->node) {
382         case GREP_NODE_TRUE:
383         case GREP_NODE_ATOM:
384                 break;
385         case GREP_NODE_NOT:
386                 free_pattern_expr(x->u.unary);
387                 break;
388         case GREP_NODE_AND:
389         case GREP_NODE_OR:
390                 free_pattern_expr(x->u.binary.left);
391                 free_pattern_expr(x->u.binary.right);
392                 break;
393         }
394         free(x);
395 }
396
397 void free_grep_patterns(struct grep_opt *opt)
398 {
399         struct grep_pat *p, *n;
400
401         for (p = opt->pattern_list; p; p = n) {
402                 n = p->next;
403                 switch (p->token) {
404                 case GREP_PATTERN: /* atom */
405                 case GREP_PATTERN_HEAD:
406                 case GREP_PATTERN_BODY:
407                         if (p->pcre_regexp)
408                                 free_pcre_regexp(p);
409                         else
410                                 regfree(&p->regexp);
411                         break;
412                 default:
413                         break;
414                 }
415                 free(p);
416         }
417
418         if (!opt->extended)
419                 return;
420         free_pattern_expr(opt->pattern_expression);
421 }
422
423 static char *end_of_line(char *cp, unsigned long *left)
424 {
425         unsigned long l = *left;
426         while (l && *cp != '\n') {
427                 l--;
428                 cp++;
429         }
430         *left = l;
431         return cp;
432 }
433
434 static int word_char(char ch)
435 {
436         return isalnum(ch) || ch == '_';
437 }
438
439 static void output_color(struct grep_opt *opt, const void *data, size_t size,
440                          const char *color)
441 {
442         if (opt->color && color && color[0]) {
443                 opt->output(opt, color, strlen(color));
444                 opt->output(opt, data, size);
445                 opt->output(opt, GIT_COLOR_RESET, strlen(GIT_COLOR_RESET));
446         } else
447                 opt->output(opt, data, size);
448 }
449
450 static void output_sep(struct grep_opt *opt, char sign)
451 {
452         if (opt->null_following_name)
453                 opt->output(opt, "\0", 1);
454         else
455                 output_color(opt, &sign, 1, opt->color_sep);
456 }
457
458 static void show_name(struct grep_opt *opt, const char *name)
459 {
460         output_color(opt, name, strlen(name), opt->color_filename);
461         opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
462 }
463
464 static int fixmatch(struct grep_pat *p, char *line, char *eol,
465                     regmatch_t *match)
466 {
467         char *hit;
468
469         if (p->ignore_case) {
470                 char *s = line;
471                 do {
472                         hit = strcasestr(s, p->pattern);
473                         if (hit)
474                                 break;
475                         s += strlen(s) + 1;
476                 } while (s < eol);
477         } else
478                 hit = memmem(line, eol - line, p->pattern, p->patternlen);
479
480         if (!hit) {
481                 match->rm_so = match->rm_eo = -1;
482                 return REG_NOMATCH;
483         }
484         else {
485                 match->rm_so = hit - line;
486                 match->rm_eo = match->rm_so + p->patternlen;
487                 return 0;
488         }
489 }
490
491 static int regmatch(const regex_t *preg, char *line, char *eol,
492                     regmatch_t *match, int eflags)
493 {
494 #ifdef REG_STARTEND
495         match->rm_so = 0;
496         match->rm_eo = eol - line;
497         eflags |= REG_STARTEND;
498 #endif
499         return regexec(preg, line, 1, match, eflags);
500 }
501
502 static int patmatch(struct grep_pat *p, char *line, char *eol,
503                     regmatch_t *match, int eflags)
504 {
505         int hit;
506
507         if (p->fixed)
508                 hit = !fixmatch(p, line, eol, match);
509         else if (p->pcre_regexp)
510                 hit = !pcrematch(p, line, eol, match, eflags);
511         else
512                 hit = !regmatch(&p->regexp, line, eol, match, eflags);
513
514         return hit;
515 }
516
517 static int strip_timestamp(char *bol, char **eol_p)
518 {
519         char *eol = *eol_p;
520         int ch;
521
522         while (bol < --eol) {
523                 if (*eol != '>')
524                         continue;
525                 *eol_p = ++eol;
526                 ch = *eol;
527                 *eol = '\0';
528                 return ch;
529         }
530         return 0;
531 }
532
533 static struct {
534         const char *field;
535         size_t len;
536 } header_field[] = {
537         { "author ", 7 },
538         { "committer ", 10 },
539 };
540
541 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
542                              enum grep_context ctx,
543                              regmatch_t *pmatch, int eflags)
544 {
545         int hit = 0;
546         int saved_ch = 0;
547         const char *start = bol;
548
549         if ((p->token != GREP_PATTERN) &&
550             ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
551                 return 0;
552
553         if (p->token == GREP_PATTERN_HEAD) {
554                 const char *field;
555                 size_t len;
556                 assert(p->field < ARRAY_SIZE(header_field));
557                 field = header_field[p->field].field;
558                 len = header_field[p->field].len;
559                 if (strncmp(bol, field, len))
560                         return 0;
561                 bol += len;
562                 saved_ch = strip_timestamp(bol, &eol);
563         }
564
565  again:
566         hit = patmatch(p, bol, eol, pmatch, eflags);
567
568         if (hit && p->word_regexp) {
569                 if ((pmatch[0].rm_so < 0) ||
570                     (eol - bol) < pmatch[0].rm_so ||
571                     (pmatch[0].rm_eo < 0) ||
572                     (eol - bol) < pmatch[0].rm_eo)
573                         die("regexp returned nonsense");
574
575                 /* Match beginning must be either beginning of the
576                  * line, or at word boundary (i.e. the last char must
577                  * not be a word char).  Similarly, match end must be
578                  * either end of the line, or at word boundary
579                  * (i.e. the next char must not be a word char).
580                  */
581                 if ( ((pmatch[0].rm_so == 0) ||
582                       !word_char(bol[pmatch[0].rm_so-1])) &&
583                      ((pmatch[0].rm_eo == (eol-bol)) ||
584                       !word_char(bol[pmatch[0].rm_eo])) )
585                         ;
586                 else
587                         hit = 0;
588
589                 /* Words consist of at least one character. */
590                 if (pmatch->rm_so == pmatch->rm_eo)
591                         hit = 0;
592
593                 if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
594                         /* There could be more than one match on the
595                          * line, and the first match might not be
596                          * strict word match.  But later ones could be!
597                          * Forward to the next possible start, i.e. the
598                          * next position following a non-word char.
599                          */
600                         bol = pmatch[0].rm_so + bol + 1;
601                         while (word_char(bol[-1]) && bol < eol)
602                                 bol++;
603                         eflags |= REG_NOTBOL;
604                         if (bol < eol)
605                                 goto again;
606                 }
607         }
608         if (p->token == GREP_PATTERN_HEAD && saved_ch)
609                 *eol = saved_ch;
610         if (hit) {
611                 pmatch[0].rm_so += bol - start;
612                 pmatch[0].rm_eo += bol - start;
613         }
614         return hit;
615 }
616
617 static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
618                            enum grep_context ctx, int collect_hits)
619 {
620         int h = 0;
621         regmatch_t match;
622
623         if (!x)
624                 die("Not a valid grep expression");
625         switch (x->node) {
626         case GREP_NODE_TRUE:
627                 h = 1;
628                 break;
629         case GREP_NODE_ATOM:
630                 h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
631                 break;
632         case GREP_NODE_NOT:
633                 h = !match_expr_eval(x->u.unary, bol, eol, ctx, 0);
634                 break;
635         case GREP_NODE_AND:
636                 if (!match_expr_eval(x->u.binary.left, bol, eol, ctx, 0))
637                         return 0;
638                 h = match_expr_eval(x->u.binary.right, bol, eol, ctx, 0);
639                 break;
640         case GREP_NODE_OR:
641                 if (!collect_hits)
642                         return (match_expr_eval(x->u.binary.left,
643                                                 bol, eol, ctx, 0) ||
644                                 match_expr_eval(x->u.binary.right,
645                                                 bol, eol, ctx, 0));
646                 h = match_expr_eval(x->u.binary.left, bol, eol, ctx, 0);
647                 x->u.binary.left->hit |= h;
648                 h |= match_expr_eval(x->u.binary.right, bol, eol, ctx, 1);
649                 break;
650         default:
651                 die("Unexpected node type (internal error) %d", x->node);
652         }
653         if (collect_hits)
654                 x->hit |= h;
655         return h;
656 }
657
658 static int match_expr(struct grep_opt *opt, char *bol, char *eol,
659                       enum grep_context ctx, int collect_hits)
660 {
661         struct grep_expr *x = opt->pattern_expression;
662         return match_expr_eval(x, bol, eol, ctx, collect_hits);
663 }
664
665 static int match_line(struct grep_opt *opt, char *bol, char *eol,
666                       enum grep_context ctx, int collect_hits)
667 {
668         struct grep_pat *p;
669         regmatch_t match;
670
671         if (opt->extended)
672                 return match_expr(opt, bol, eol, ctx, collect_hits);
673
674         /* we do not call with collect_hits without being extended */
675         for (p = opt->pattern_list; p; p = p->next) {
676                 if (match_one_pattern(p, bol, eol, ctx, &match, 0))
677                         return 1;
678         }
679         return 0;
680 }
681
682 static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
683                               enum grep_context ctx,
684                               regmatch_t *pmatch, int eflags)
685 {
686         regmatch_t match;
687
688         if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
689                 return 0;
690         if (match.rm_so < 0 || match.rm_eo < 0)
691                 return 0;
692         if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
693                 if (match.rm_so > pmatch->rm_so)
694                         return 1;
695                 if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
696                         return 1;
697         }
698         pmatch->rm_so = match.rm_so;
699         pmatch->rm_eo = match.rm_eo;
700         return 1;
701 }
702
703 static int next_match(struct grep_opt *opt, char *bol, char *eol,
704                       enum grep_context ctx, regmatch_t *pmatch, int eflags)
705 {
706         struct grep_pat *p;
707         int hit = 0;
708
709         pmatch->rm_so = pmatch->rm_eo = -1;
710         if (bol < eol) {
711                 for (p = opt->pattern_list; p; p = p->next) {
712                         switch (p->token) {
713                         case GREP_PATTERN: /* atom */
714                         case GREP_PATTERN_HEAD:
715                         case GREP_PATTERN_BODY:
716                                 hit |= match_next_pattern(p, bol, eol, ctx,
717                                                           pmatch, eflags);
718                                 break;
719                         default:
720                                 break;
721                         }
722                 }
723         }
724         return hit;
725 }
726
727 static void show_line(struct grep_opt *opt, char *bol, char *eol,
728                       const char *name, unsigned lno, char sign)
729 {
730         int rest = eol - bol;
731         char *line_color = NULL;
732
733         if (opt->pre_context || opt->post_context) {
734                 if (opt->last_shown == 0) {
735                         if (opt->show_hunk_mark) {
736                                 output_color(opt, "--", 2, opt->color_sep);
737                                 opt->output(opt, "\n", 1);
738                         }
739                 } else if (lno > opt->last_shown + 1) {
740                         output_color(opt, "--", 2, opt->color_sep);
741                         opt->output(opt, "\n", 1);
742                 }
743         }
744         opt->last_shown = lno;
745
746         if (opt->pathname) {
747                 output_color(opt, name, strlen(name), opt->color_filename);
748                 output_sep(opt, sign);
749         }
750         if (opt->linenum) {
751                 char buf[32];
752                 snprintf(buf, sizeof(buf), "%d", lno);
753                 output_color(opt, buf, strlen(buf), opt->color_lineno);
754                 output_sep(opt, sign);
755         }
756         if (opt->color) {
757                 regmatch_t match;
758                 enum grep_context ctx = GREP_CONTEXT_BODY;
759                 int ch = *eol;
760                 int eflags = 0;
761
762                 if (sign == ':')
763                         line_color = opt->color_selected;
764                 else if (sign == '-')
765                         line_color = opt->color_context;
766                 else if (sign == '=')
767                         line_color = opt->color_function;
768                 *eol = '\0';
769                 while (next_match(opt, bol, eol, ctx, &match, eflags)) {
770                         if (match.rm_so == match.rm_eo)
771                                 break;
772
773                         output_color(opt, bol, match.rm_so, line_color);
774                         output_color(opt, bol + match.rm_so,
775                                      match.rm_eo - match.rm_so,
776                                      opt->color_match);
777                         bol += match.rm_eo;
778                         rest -= match.rm_eo;
779                         eflags = REG_NOTBOL;
780                 }
781                 *eol = ch;
782         }
783         output_color(opt, bol, rest, line_color);
784         opt->output(opt, "\n", 1);
785 }
786
787 static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
788 {
789         xdemitconf_t *xecfg = opt->priv;
790         if (xecfg && xecfg->find_func) {
791                 char buf[1];
792                 return xecfg->find_func(bol, eol - bol, buf, 1,
793                                         xecfg->find_func_priv) >= 0;
794         }
795
796         if (bol == eol)
797                 return 0;
798         if (isalpha(*bol) || *bol == '_' || *bol == '$')
799                 return 1;
800         return 0;
801 }
802
803 static void show_funcname_line(struct grep_opt *opt, const char *name,
804                                char *buf, char *bol, unsigned lno)
805 {
806         while (bol > buf) {
807                 char *eol = --bol;
808
809                 while (bol > buf && bol[-1] != '\n')
810                         bol--;
811                 lno--;
812
813                 if (lno <= opt->last_shown)
814                         break;
815
816                 if (match_funcname(opt, bol, eol)) {
817                         show_line(opt, bol, eol, name, lno, '=');
818                         break;
819                 }
820         }
821 }
822
823 static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
824                              char *bol, unsigned lno)
825 {
826         unsigned cur = lno, from = 1, funcname_lno = 0;
827         int funcname_needed = opt->funcname;
828
829         if (opt->pre_context < lno)
830                 from = lno - opt->pre_context;
831         if (from <= opt->last_shown)
832                 from = opt->last_shown + 1;
833
834         /* Rewind. */
835         while (bol > buf && cur > from) {
836                 char *eol = --bol;
837
838                 while (bol > buf && bol[-1] != '\n')
839                         bol--;
840                 cur--;
841                 if (funcname_needed && match_funcname(opt, bol, eol)) {
842                         funcname_lno = cur;
843                         funcname_needed = 0;
844                 }
845         }
846
847         /* We need to look even further back to find a function signature. */
848         if (opt->funcname && funcname_needed)
849                 show_funcname_line(opt, name, buf, bol, cur);
850
851         /* Back forward. */
852         while (cur < lno) {
853                 char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
854
855                 while (*eol != '\n')
856                         eol++;
857                 show_line(opt, bol, eol, name, cur, sign);
858                 bol = eol + 1;
859                 cur++;
860         }
861 }
862
863 static int should_lookahead(struct grep_opt *opt)
864 {
865         struct grep_pat *p;
866
867         if (opt->extended)
868                 return 0; /* punt for too complex stuff */
869         if (opt->invert)
870                 return 0;
871         for (p = opt->pattern_list; p; p = p->next) {
872                 if (p->token != GREP_PATTERN)
873                         return 0; /* punt for "header only" and stuff */
874         }
875         return 1;
876 }
877
878 static int look_ahead(struct grep_opt *opt,
879                       unsigned long *left_p,
880                       unsigned *lno_p,
881                       char **bol_p)
882 {
883         unsigned lno = *lno_p;
884         char *bol = *bol_p;
885         struct grep_pat *p;
886         char *sp, *last_bol;
887         regoff_t earliest = -1;
888
889         for (p = opt->pattern_list; p; p = p->next) {
890                 int hit;
891                 regmatch_t m;
892
893                 hit = patmatch(p, bol, bol + *left_p, &m, 0);
894                 if (!hit || m.rm_so < 0 || m.rm_eo < 0)
895                         continue;
896                 if (earliest < 0 || m.rm_so < earliest)
897                         earliest = m.rm_so;
898         }
899
900         if (earliest < 0) {
901                 *bol_p = bol + *left_p;
902                 *left_p = 0;
903                 return 1;
904         }
905         for (sp = bol + earliest; bol < sp && sp[-1] != '\n'; sp--)
906                 ; /* find the beginning of the line */
907         last_bol = sp;
908
909         for (sp = bol; sp < last_bol; sp++) {
910                 if (*sp == '\n')
911                         lno++;
912         }
913         *left_p -= last_bol - bol;
914         *bol_p = last_bol;
915         *lno_p = lno;
916         return 0;
917 }
918
919 int grep_threads_ok(const struct grep_opt *opt)
920 {
921         /* If this condition is true, then we may use the attribute
922          * machinery in grep_buffer_1. The attribute code is not
923          * thread safe, so we disable the use of threads.
924          */
925         if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
926             !opt->name_only)
927                 return 0;
928
929         return 1;
930 }
931
932 static void std_output(struct grep_opt *opt, const void *buf, size_t size)
933 {
934         fwrite(buf, size, 1, stdout);
935 }
936
937 static int grep_buffer_1(struct grep_opt *opt, const char *name,
938                          char *buf, unsigned long size, int collect_hits)
939 {
940         char *bol = buf;
941         unsigned long left = size;
942         unsigned lno = 1;
943         unsigned last_hit = 0;
944         int binary_match_only = 0;
945         unsigned count = 0;
946         int try_lookahead = 0;
947         enum grep_context ctx = GREP_CONTEXT_HEAD;
948         xdemitconf_t xecfg;
949
950         if (!opt->output)
951                 opt->output = std_output;
952
953         if (opt->last_shown && (opt->pre_context || opt->post_context) &&
954             opt->output == std_output)
955                 opt->show_hunk_mark = 1;
956         opt->last_shown = 0;
957
958         switch (opt->binary) {
959         case GREP_BINARY_DEFAULT:
960                 if (buffer_is_binary(buf, size))
961                         binary_match_only = 1;
962                 break;
963         case GREP_BINARY_NOMATCH:
964                 if (buffer_is_binary(buf, size))
965                         return 0; /* Assume unmatch */
966                 break;
967         case GREP_BINARY_TEXT:
968                 break;
969         default:
970                 die("bug: unknown binary handling mode");
971         }
972
973         memset(&xecfg, 0, sizeof(xecfg));
974         if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
975             !opt->name_only && !binary_match_only && !collect_hits) {
976                 struct userdiff_driver *drv = userdiff_find_by_path(name);
977                 if (drv && drv->funcname.pattern) {
978                         const struct userdiff_funcname *pe = &drv->funcname;
979                         xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
980                         opt->priv = &xecfg;
981                 }
982         }
983         try_lookahead = should_lookahead(opt);
984
985         while (left) {
986                 char *eol, ch;
987                 int hit;
988
989                 /*
990                  * look_ahead() skips quickly to the line that possibly
991                  * has the next hit; don't call it if we need to do
992                  * something more than just skipping the current line
993                  * in response to an unmatch for the current line.  E.g.
994                  * inside a post-context window, we will show the current
995                  * line as a context around the previous hit when it
996                  * doesn't hit.
997                  */
998                 if (try_lookahead
999                     && !(last_hit
1000                          && lno <= last_hit + opt->post_context)
1001                     && look_ahead(opt, &left, &lno, &bol))
1002                         break;
1003                 eol = end_of_line(bol, &left);
1004                 ch = *eol;
1005                 *eol = 0;
1006
1007                 if ((ctx == GREP_CONTEXT_HEAD) && (eol == bol))
1008                         ctx = GREP_CONTEXT_BODY;
1009
1010                 hit = match_line(opt, bol, eol, ctx, collect_hits);
1011                 *eol = ch;
1012
1013                 if (collect_hits)
1014                         goto next_line;
1015
1016                 /* "grep -v -e foo -e bla" should list lines
1017                  * that do not have either, so inversion should
1018                  * be done outside.
1019                  */
1020                 if (opt->invert)
1021                         hit = !hit;
1022                 if (opt->unmatch_name_only) {
1023                         if (hit)
1024                                 return 0;
1025                         goto next_line;
1026                 }
1027                 if (hit) {
1028                         count++;
1029                         if (opt->status_only)
1030                                 return 1;
1031                         if (opt->name_only) {
1032                                 show_name(opt, name);
1033                                 return 1;
1034                         }
1035                         if (opt->count)
1036                                 goto next_line;
1037                         if (binary_match_only) {
1038                                 opt->output(opt, "Binary file ", 12);
1039                                 output_color(opt, name, strlen(name),
1040                                              opt->color_filename);
1041                                 opt->output(opt, " matches\n", 9);
1042                                 return 1;
1043                         }
1044                         /* Hit at this line.  If we haven't shown the
1045                          * pre-context lines, we would need to show them.
1046                          */
1047                         if (opt->pre_context)
1048                                 show_pre_context(opt, name, buf, bol, lno);
1049                         else if (opt->funcname)
1050                                 show_funcname_line(opt, name, buf, bol, lno);
1051                         show_line(opt, bol, eol, name, lno, ':');
1052                         last_hit = lno;
1053                 }
1054                 else if (last_hit &&
1055                          lno <= last_hit + opt->post_context) {
1056                         /* If the last hit is within the post context,
1057                          * we need to show this line.
1058                          */
1059                         show_line(opt, bol, eol, name, lno, '-');
1060                 }
1061
1062         next_line:
1063                 bol = eol + 1;
1064                 if (!left)
1065                         break;
1066                 left--;
1067                 lno++;
1068         }
1069
1070         if (collect_hits)
1071                 return 0;
1072
1073         if (opt->status_only)
1074                 return 0;
1075         if (opt->unmatch_name_only) {
1076                 /* We did not see any hit, so we want to show this */
1077                 show_name(opt, name);
1078                 return 1;
1079         }
1080
1081         xdiff_clear_find_func(&xecfg);
1082         opt->priv = NULL;
1083
1084         /* NEEDSWORK:
1085          * The real "grep -c foo *.c" gives many "bar.c:0" lines,
1086          * which feels mostly useless but sometimes useful.  Maybe
1087          * make it another option?  For now suppress them.
1088          */
1089         if (opt->count && count) {
1090                 char buf[32];
1091                 output_color(opt, name, strlen(name), opt->color_filename);
1092                 output_sep(opt, ':');
1093                 snprintf(buf, sizeof(buf), "%u\n", count);
1094                 opt->output(opt, buf, strlen(buf));
1095                 return 1;
1096         }
1097         return !!last_hit;
1098 }
1099
1100 static void clr_hit_marker(struct grep_expr *x)
1101 {
1102         /* All-hit markers are meaningful only at the very top level
1103          * OR node.
1104          */
1105         while (1) {
1106                 x->hit = 0;
1107                 if (x->node != GREP_NODE_OR)
1108                         return;
1109                 x->u.binary.left->hit = 0;
1110                 x = x->u.binary.right;
1111         }
1112 }
1113
1114 static int chk_hit_marker(struct grep_expr *x)
1115 {
1116         /* Top level nodes have hit markers.  See if they all are hits */
1117         while (1) {
1118                 if (x->node != GREP_NODE_OR)
1119                         return x->hit;
1120                 if (!x->u.binary.left->hit)
1121                         return 0;
1122                 x = x->u.binary.right;
1123         }
1124 }
1125
1126 int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size)
1127 {
1128         /*
1129          * we do not have to do the two-pass grep when we do not check
1130          * buffer-wide "all-match".
1131          */
1132         if (!opt->all_match)
1133                 return grep_buffer_1(opt, name, buf, size, 0);
1134
1135         /* Otherwise the toplevel "or" terms hit a bit differently.
1136          * We first clear hit markers from them.
1137          */
1138         clr_hit_marker(opt->pattern_expression);
1139         grep_buffer_1(opt, name, buf, size, 1);
1140
1141         if (!chk_hit_marker(opt->pattern_expression))
1142                 return 0;
1143
1144         return grep_buffer_1(opt, name, buf, size, 0);
1145 }