From 7ed36f56e33bd838d06521a37a916516397e9e8b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 3 May 2006 21:03:25 -0700 Subject: [PATCH 1/3] builtin-grep: terminate correctly at EOF It barfed and segfaulted with an incomplete line. Signed-off-by: Junio C Hamano --- builtin-grep.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builtin-grep.c b/builtin-grep.c index 2124fa62e8..e87b5cb48d 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -264,6 +264,8 @@ static int grep_buffer(struct grep_opt *opt, const char *name, } *eol = ch; bol = eol + 1; + if (!left) + break; left--; lno++; } From b8d0f5a00313bc5fb173f77c9a91a94f94a5aa1b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 3 May 2006 21:05:29 -0700 Subject: [PATCH 2/3] builtin-grep: binary files -a and -I Signed-off-by: Junio C Hamano --- builtin-grep.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/builtin-grep.c b/builtin-grep.c index e87b5cb48d..0d6115763b 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -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; From e23d2d6b765162902bd8b722e1659f002b97a302 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 3 May 2006 21:46:29 -0700 Subject: [PATCH 3/3] builtin-grep: -L (--files-without-match). Signed-off-by: Junio C Hamano --- builtin-grep.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/builtin-grep.c b/builtin-grep.c index 0d6115763b..c89ee33a1e 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -93,6 +93,7 @@ struct grep_opt { unsigned linenum:1; unsigned invert:1; unsigned name_only:1; + unsigned unmatch_name_only:1; unsigned count:1; unsigned word_regexp:1; #define GREP_BINARY_DEFAULT 0 @@ -241,6 +242,11 @@ static int grep_buffer(struct grep_opt *opt, const char *name, */ if (opt->invert) hit = !hit; + if (opt->unmatch_name_only) { + if (hit) + return 0; + goto next_line; + } if (hit) { count++; if (binary_match_only) { @@ -297,6 +303,8 @@ static int grep_buffer(struct grep_opt *opt, const char *name, prev->bol = bol; prev->eol = eol; } + + next_line: *eol = ch; bol = eol + 1; if (!left) @@ -304,6 +312,13 @@ static int grep_buffer(struct grep_opt *opt, const char *name, left--; lno++; } + + if (opt->unmatch_name_only) { + /* We did not see any hit, so we want to show this */ + printf("%s\n", name); + return 1; + } + /* NEEDSWORK: * The real "grep -c foo *.c" gives many "bar.c:0" lines, * which feels mostly useless but sometimes useful. Maybe @@ -532,6 +547,11 @@ int cmd_grep(int argc, const char **argv, char **envp) opt.name_only = 1; continue; } + if (!strcmp("-L", arg) || + !strcmp("--files-without-match", arg)) { + opt.unmatch_name_only = 1; + continue; + } if (!strcmp("-c", arg) || !strcmp("--count", arg)) { opt.count = 1;