builtin-grep: binary files -a and -I

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff --git a/builtin-grep.c b/builtin-grep.c
index e87b5cb..0d61157 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -95,6 +95,10 @@
 	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 @@
 	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 @@
 	} *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 @@
 			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 @@
 			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;