builtin-grep: binary files -a and -I
authorJunio C Hamano <junkio@cox.net>
Thu, 4 May 2006 04:05:29 +0000 (21:05 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 4 May 2006 04:05:29 +0000 (21:05 -0700)
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-grep.c

index e87b5cb48d6eda5ada9a3cd9bb505d8abe36fd41..0d6115763bf3c9f409518daa000f51951a7f0c95 100644 (file)
@@ -95,6 +95,10 @@ struct grep_opt {
        unsigned name_only:1;
        unsigned count:1;
        unsigned word_regexp:1;
+#define GREP_BINARY_DEFAULT    0
+#define GREP_BINARY_NOMATCH    1
+#define GREP_BINARY_TEXT       2
+       unsigned binary:2;
        int regflags;
        unsigned pre_context;
        unsigned post_context;
@@ -148,6 +152,19 @@ static void show_line(struct grep_opt *opt, const char *bol, const char *eol,
        printf("%.*s\n", (int)(eol-bol), bol);
 }
 
+/*
+ * NEEDSWORK: share code with diff.c
+ */
+#define FIRST_FEW_BYTES 8000
+static int buffer_is_binary(const char *ptr, unsigned long size)
+{
+       if (FIRST_FEW_BYTES < size)
+               size = FIRST_FEW_BYTES;
+       if (memchr(ptr, 0, size))
+               return 1;
+       return 0;
+}
+
 static int grep_buffer(struct grep_opt *opt, const char *name,
                       char *buf, unsigned long size)
 {
@@ -160,9 +177,23 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
        } *prev = NULL, *pcl;
        unsigned last_hit = 0;
        unsigned last_shown = 0;
+       int binary_match_only = 0;
        const char *hunk_mark = "";
        unsigned count = 0;
 
+       if (buffer_is_binary(buf, size)) {
+               switch (opt->binary) {
+               case GREP_BINARY_DEFAULT:
+                       binary_match_only = 1;
+                       break;
+               case GREP_BINARY_NOMATCH:
+                       return 0; /* Assume unmatch */
+                       break;
+               default:
+                       break;
+               }
+       }
+
        if (opt->pre_context)
                prev = xcalloc(opt->pre_context, sizeof(*prev));
        if (opt->pre_context || opt->post_context)
@@ -212,6 +243,10 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
                        hit = !hit;
                if (hit) {
                        count++;
+                       if (binary_match_only) {
+                               printf("Binary file %s matches\n", name);
+                               return 1;
+                       }
                        if (opt->name_only) {
                                printf("%s\n", name);
                                return 1;
@@ -453,11 +488,20 @@ int cmd_grep(int argc, const char **argv, char **envp)
                        cached = 1;
                        continue;
                }
+               if (!strcmp("-a", arg) ||
+                   !strcmp("--text", arg)) {
+                       opt.binary = GREP_BINARY_TEXT;
+                       continue;
+               }
                if (!strcmp("-i", arg) ||
                    !strcmp("--ignore-case", arg)) {
                        opt.regflags |= REG_ICASE;
                        continue;
                }
+               if (!strcmp("-I", arg)) {
+                       opt.binary = GREP_BINARY_NOMATCH;
+                       continue;
+               }
                if (!strcmp("-v", arg) ||
                    !strcmp("--invert-match", arg)) {
                        opt.invert = 1;