Code

Remove obsolete bug warning in man git-update-server-info
[git.git] / grep.c
diff --git a/grep.c b/grep.c
index bdcff7b9e4959b618028edb6759fb4aa36db45f1..f3a27d7d6e141bd8813b978edbe33d16aa764fb4 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -192,7 +192,8 @@ void compile_grep_patterns(struct grep_opt *opt)
         * A classic recursive descent parser would do.
         */
        p = opt->pattern_list;
-       opt->pattern_expression = compile_pattern_expr(&p);
+       if (p)
+               opt->pattern_expression = compile_pattern_expr(&p);
        if (p)
                die("incomplete pattern expression: %s", p->pattern);
 }
@@ -253,18 +254,6 @@ static int word_char(char ch)
        return isalnum(ch) || ch == '_';
 }
 
-static void show_line(struct grep_opt *opt, const char *bol, const char *eol,
-                     const char *name, unsigned lno, char sign)
-{
-       if (opt->null_following_name)
-               sign = '\0';
-       if (opt->pathname)
-               printf("%s%c", name, sign);
-       if (opt->linenum)
-               printf("%d%c", lno, sign);
-       printf("%.*s\n", (int)(eol-bol), bol);
-}
-
 static void show_name(struct grep_opt *opt, const char *name)
 {
        printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
@@ -437,6 +426,84 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
        return 0;
 }
 
+static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
+                             enum grep_context ctx,
+                             regmatch_t *pmatch, int eflags)
+{
+       regmatch_t match;
+
+       if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
+               return 0;
+       if (match.rm_so < 0 || match.rm_eo < 0)
+               return 0;
+       if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
+               if (match.rm_so > pmatch->rm_so)
+                       return 1;
+               if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
+                       return 1;
+       }
+       pmatch->rm_so = match.rm_so;
+       pmatch->rm_eo = match.rm_eo;
+       return 1;
+}
+
+static int next_match(struct grep_opt *opt, char *bol, char *eol,
+                     enum grep_context ctx, regmatch_t *pmatch, int eflags)
+{
+       struct grep_pat *p;
+       int hit = 0;
+
+       pmatch->rm_so = pmatch->rm_eo = -1;
+       if (bol < eol) {
+               for (p = opt->pattern_list; p; p = p->next) {
+                       switch (p->token) {
+                       case GREP_PATTERN: /* atom */
+                       case GREP_PATTERN_HEAD:
+                       case GREP_PATTERN_BODY:
+                               hit |= match_next_pattern(p, bol, eol, ctx,
+                                                         pmatch, eflags);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+       return hit;
+}
+
+static void show_line(struct grep_opt *opt, char *bol, char *eol,
+                     const char *name, unsigned lno, char sign)
+{
+       int rest = eol - bol;
+
+       if (opt->null_following_name)
+               sign = '\0';
+       if (opt->pathname)
+               printf("%s%c", name, sign);
+       if (opt->linenum)
+               printf("%d%c", lno, sign);
+       if (opt->color) {
+               regmatch_t match;
+               enum grep_context ctx = GREP_CONTEXT_BODY;
+               int ch = *eol;
+               int eflags = 0;
+
+               *eol = '\0';
+               while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+                       printf("%.*s%s%.*s%s",
+                              (int)match.rm_so, bol,
+                              opt->color_match,
+                              (int)(match.rm_eo - match.rm_so), bol + match.rm_so,
+                              GIT_COLOR_RESET);
+                       bol += match.rm_eo;
+                       rest -= match.rm_eo;
+                       eflags = REG_NOTBOL;
+               }
+               *eol = ch;
+       }
+       printf("%.*s\n", rest, bol);
+}
+
 static int grep_buffer_1(struct grep_opt *opt, const char *name,
                         char *buf, unsigned long size, int collect_hits)
 {