@matheusbsbs / matheus-bagliano / commits / 3e230fa1b2
Fork 0

grep: use parseopt

Convert git-grep to parseopt. The bitfields in struct grep_opt are converted to full ints, increasing its size. This shouldn't be a problem as there is only a single instance in memory. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed May 7, 2009 at 21:46 UTC 3e230fa1b2ba3aa1a207c4399a1b93e41b103dfb
2 files changed +194 -240
builtin-grep.c
+180 -226
@@ -10,6 +10,7 @@
10 #include "tag.h"
11 #include "tree-walk.h"
12 #include "builtin.h"
13 +#include "parse-options.h"
14 #include "grep.h"
15
16 #ifndef NO_EXTERNAL_GREP
@@ -20,6 +21,11 @@
21 #endif
22 #endif
23
24 +static char const * const grep_usage[] = {
25 + "git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
26 + NULL
27 +};
28 +
29 static int grep_config(const char *var, const char *value, void *cb)
30 {
31 struct grep_opt *opt = cb;
@@ -559,15 +565,86 @@ static int grep_object(struct grep_opt *opt, const char **paths,
565 die("unable to grep from object of type %s", typename(obj->type));
566 }
567
562 -static const char builtin_grep_usage[] =
563 -"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
568 +int context_callback(const struct option *opt, const char *arg, int unset)
569 +{
570 + struct grep_opt *grep_opt = opt->value;
571 + int value;
572 + const char *endp;
573 +
574 + if (unset) {
575 + grep_opt->pre_context = grep_opt->post_context = 0;
576 + return 0;
577 + }
578 + value = strtol(arg, (char **)&endp, 10);
579 + if (*endp) {
580 + return error("switch `%c' expects a numerical value",
581 + opt->short_name);
582 + }
583 + grep_opt->pre_context = grep_opt->post_context = value;
584 + return 0;
585 +}
586 +
587 +int file_callback(const struct option *opt, const char *arg, int unset)
588 +{
589 + struct grep_opt *grep_opt = opt->value;
590 + FILE *patterns;
591 + int lno = 0;
592 + struct strbuf sb;
593 +
594 + patterns = fopen(arg, "r");
595 + if (!patterns)
596 + die("'%s': %s", arg, strerror(errno));
597 + while (strbuf_getline(&sb, patterns, '\n') == 0) {
598 + /* ignore empty line like grep does */
599 + if (sb.len == 0)
600 + continue;
601 + append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg,
602 + ++lno, GREP_PATTERN);
603 + }
604 + fclose(patterns);
605 + strbuf_release(&sb);
606 + return 0;
607 +}
608 +
609 +int not_callback(const struct option *opt, const char *arg, int unset)
610 +{
611 + struct grep_opt *grep_opt = opt->value;
612 + append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
613 + return 0;
614 +}
615 +
616 +int and_callback(const struct option *opt, const char *arg, int unset)
617 +{
618 + struct grep_opt *grep_opt = opt->value;
619 + append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
620 + return 0;
621 +}
622 +
623 +int open_callback(const struct option *opt, const char *arg, int unset)
624 +{
625 + struct grep_opt *grep_opt = opt->value;
626 + append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
627 + return 0;
628 +}
629 +
630 +int close_callback(const struct option *opt, const char *arg, int unset)
631 +{
632 + struct grep_opt *grep_opt = opt->value;
633 + append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
634 + return 0;
635 +}
636 +
637 +int pattern_callback(const struct option *opt, const char *arg, int unset)
638 +{
639 + struct grep_opt *grep_opt = opt->value;
640 + append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
641 + return 0;
642 +}
643
565 -static const char emsg_invalid_context_len[] =
566 -"%s: invalid context length argument";
567 -static const char emsg_missing_context_len[] =
568 -"missing context length argument";
569 -static const char emsg_missing_argument[] =
570 -"option requires an argument -%s";
644 +int help_callback(const struct option *opt, const char *arg, int unset)
645 +{
646 + return -1;
647 +}
648
649 int cmd_grep(int argc, const char **argv, const char *prefix)
650 {
@@ -579,6 +656,89 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
656 struct object_array list = { 0, 0, NULL };
657 const char **paths = NULL;
658 int i;
659 + int dummy;
660 + struct option options[] = {
661 + OPT_BOOLEAN(0, "cached", &cached,
662 + "search in index instead of in the work tree"),
663 + OPT_GROUP(""),
664 + OPT_BOOLEAN('v', "invert-match", &opt.invert,
665 + "show non-matching lines"),
666 + OPT_BIT('i', "ignore-case", &opt.regflags,
667 + "case insensitive matching", REG_ICASE),
668 + OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
669 + "match patterns only at word boundaries"),
670 + OPT_SET_INT('a', "text", &opt.binary,
671 + "process binary files as text", GREP_BINARY_TEXT),
672 + OPT_SET_INT('I', NULL, &opt.binary,
673 + "don't match patterns in binary files",
674 + GREP_BINARY_NOMATCH),
675 + OPT_GROUP(""),
676 + OPT_BIT('E', "extended-regexp", &opt.regflags,
677 + "use extended POSIX regular expressions", REG_EXTENDED),
678 + OPT_NEGBIT('G', "basic-regexp", &opt.regflags,
679 + "use basic POSIX regular expressions (default)",
680 + REG_EXTENDED),
681 + OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
682 + "interpret patterns as fixed strings"),
683 + OPT_GROUP(""),
684 + OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
685 + OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
686 + OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
687 + OPT_NEGBIT(0, "full-name", &opt.relative,
688 + "show filenames relative to top directory", 1),
689 + OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
690 + "show only filenames instead of matching lines"),
691 + OPT_BOOLEAN(0, "name-only", &opt.name_only,
692 + "synonym for --files-with-matches"),
693 + OPT_BOOLEAN('L', "files-without-match",
694 + &opt.unmatch_name_only,
695 + "show only the names of files without match"),
696 + OPT_BOOLEAN('z', "null", &opt.null_following_name,
697 + "print NUL after filenames"),
698 + OPT_BOOLEAN('c', "count", &opt.count,
699 + "show the number of matches instead of matching lines"),
700 + OPT_SET_INT(0, "color", &opt.color, "highlight matches", 1),
701 + OPT_GROUP(""),
702 + OPT_CALLBACK('C', NULL, &opt, "n",
703 + "show <n> context lines before and after matches",
704 + context_callback),
705 + OPT_INTEGER('B', NULL, &opt.pre_context,
706 + "show <n> context lines before matches"),
707 + OPT_INTEGER('A', NULL, &opt.post_context,
708 + "show <n> context lines after matches"),
709 + OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
710 + context_callback),
711 + OPT_GROUP(""),
712 + OPT_CALLBACK('f', NULL, &opt, "file",
713 + "read patterns from file", file_callback),
714 + { OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
715 + "match <pattern>", PARSE_OPT_NONEG, pattern_callback },
716 + { OPTION_CALLBACK, 0, "and", &opt, NULL,
717 + "combine patterns specified with -e",
718 + PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
719 + OPT_BOOLEAN(0, "or", &dummy, ""),
720 + { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
721 + PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
722 + { OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
723 + PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
724 + open_callback },
725 + { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
726 + PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
727 + close_callback },
728 + OPT_BOOLEAN(0, "all-match", &opt.all_match,
729 + "show only matches from files that match all patterns"),
730 + OPT_GROUP(""),
731 +#if NO_EXTERNAL_GREP
732 + OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
733 + "allow calling of grep(1) (ignored by this build)"),
734 +#else
735 + OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
736 + "allow calling of grep(1) (default)"),
737 +#endif
738 + { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
739 + PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
740 + OPT_END()
741 + };
742
743 memset(&opt, 0, sizeof(opt));
744 opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
@@ -603,223 +763,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
763 * unrecognized non option is the beginning of the refs list
764 * that continues up to the -- (if exists), and then paths.
765 */
606 -
607 - while (1 < argc) {
608 - const char *arg = argv[1];
609 - argc--; argv++;
610 - if (!strcmp("--cached", arg)) {
611 - cached = 1;
612 - continue;
613 - }
614 - if (!strcmp("--no-ext-grep", arg)) {
615 - external_grep_allowed = 0;
616 - continue;
617 - }
618 - if (!strcmp("-a", arg) ||
619 - !strcmp("--text", arg)) {
620 - opt.binary = GREP_BINARY_TEXT;
621 - continue;
622 - }
623 - if (!strcmp("-i", arg) ||
624 - !strcmp("--ignore-case", arg)) {
625 - opt.regflags |= REG_ICASE;
626 - continue;
627 - }
628 - if (!strcmp("-I", arg)) {
629 - opt.binary = GREP_BINARY_NOMATCH;
630 - continue;
631 - }
632 - if (!strcmp("-v", arg) ||
633 - !strcmp("--invert-match", arg)) {
634 - opt.invert = 1;
635 - continue;
636 - }
637 - if (!strcmp("-E", arg) ||
638 - !strcmp("--extended-regexp", arg)) {
639 - opt.regflags |= REG_EXTENDED;
640 - continue;
641 - }
642 - if (!strcmp("-F", arg) ||
643 - !strcmp("--fixed-strings", arg)) {
644 - opt.fixed = 1;
645 - continue;
646 - }
647 - if (!strcmp("-G", arg) ||
648 - !strcmp("--basic-regexp", arg)) {
649 - opt.regflags &= ~REG_EXTENDED;
650 - continue;
651 - }
652 - if (!strcmp("-n", arg)) {
653 - opt.linenum = 1;
654 - continue;
655 - }
656 - if (!strcmp("-h", arg)) {
657 - opt.pathname = 0;
658 - continue;
659 - }
660 - if (!strcmp("-H", arg)) {
661 - opt.pathname = 1;
662 - continue;
663 - }
664 - if (!strcmp("-l", arg) ||
665 - !strcmp("--name-only", arg) ||
666 - !strcmp("--files-with-matches", arg)) {
667 - opt.name_only = 1;
668 - continue;
669 - }
670 - if (!strcmp("-L", arg) ||
671 - !strcmp("--files-without-match", arg)) {
672 - opt.unmatch_name_only = 1;
673 - continue;
674 - }
675 - if (!strcmp("-z", arg) ||
676 - !strcmp("--null", arg)) {
677 - opt.null_following_name = 1;
678 - continue;
679 - }
680 - if (!strcmp("-c", arg) ||
681 - !strcmp("--count", arg)) {
682 - opt.count = 1;
683 - continue;
684 - }
685 - if (!strcmp("-w", arg) ||
686 - !strcmp("--word-regexp", arg)) {
687 - opt.word_regexp = 1;
688 - continue;
689 - }
690 - if (!prefixcmp(arg, "-A") ||
691 - !prefixcmp(arg, "-B") ||
692 - !prefixcmp(arg, "-C") ||
693 - (arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
694 - unsigned num;
695 - const char *scan;
696 - switch (arg[1]) {
697 - case 'A': case 'B': case 'C':
698 - if (!arg[2]) {
699 - if (argc <= 1)
700 - die(emsg_missing_context_len);
701 - scan = *++argv;
702 - argc--;
703 - }
704 - else
705 - scan = arg + 2;
706 - break;
707 - default:
708 - scan = arg + 1;
709 - break;
710 - }
711 - if (strtoul_ui(scan, 10, &num))
712 - die(emsg_invalid_context_len, scan);
713 - switch (arg[1]) {
714 - case 'A':
715 - opt.post_context = num;
716 - break;
717 - default:
718 - case 'C':
719 - opt.post_context = num;
720 - case 'B':
721 - opt.pre_context = num;
722 - break;
723 - }
724 - continue;
725 - }
726 - if (!strcmp("-f", arg)) {
727 - FILE *patterns;
728 - int lno = 0;
729 - char buf[1024];
730 - if (argc <= 1)
731 - die(emsg_missing_argument, arg);
732 - patterns = fopen(argv[1], "r");
733 - if (!patterns)
734 - die("'%s': %s", argv[1], strerror(errno));
735 - while (fgets(buf, sizeof(buf), patterns)) {
736 - int len = strlen(buf);
737 - if (len && buf[len-1] == '\n')
738 - buf[len-1] = 0;
739 - /* ignore empty line like grep does */
740 - if (!buf[0])
741 - continue;
742 - append_grep_pattern(&opt, xstrdup(buf),
743 - argv[1], ++lno,
744 - GREP_PATTERN);
745 - }
746 - fclose(patterns);
747 - argv++;
748 - argc--;
749 - continue;
750 - }
751 - if (!strcmp("--not", arg)) {
752 - append_grep_pattern(&opt, arg, "command line", 0,
753 - GREP_NOT);
754 - continue;
755 - }
756 - if (!strcmp("--and", arg)) {
757 - append_grep_pattern(&opt, arg, "command line", 0,
758 - GREP_AND);
759 - continue;
760 - }
761 - if (!strcmp("--or", arg))
762 - continue; /* no-op */
763 - if (!strcmp("(", arg)) {
764 - append_grep_pattern(&opt, arg, "command line", 0,
765 - GREP_OPEN_PAREN);
766 - continue;
767 - }
768 - if (!strcmp(")", arg)) {
769 - append_grep_pattern(&opt, arg, "command line", 0,
770 - GREP_CLOSE_PAREN);
771 - continue;
772 - }
773 - if (!strcmp("--all-match", arg)) {
774 - opt.all_match = 1;
775 - continue;
776 - }
777 - if (!strcmp("-e", arg)) {
778 - if (1 < argc) {
779 - append_grep_pattern(&opt, argv[1],
780 - "-e option", 0,
781 - GREP_PATTERN);
782 - argv++;
783 - argc--;
784 - continue;
785 - }
786 - die(emsg_missing_argument, arg);
787 - }
788 - if (!strcmp("--full-name", arg)) {
789 - opt.relative = 0;
790 - continue;
791 - }
792 - if (!strcmp("--color", arg)) {
793 - opt.color = 1;
794 - continue;
795 - }
796 - if (!strcmp("--no-color", arg)) {
797 - opt.color = 0;
798 - continue;
799 - }
800 - if (!strcmp("--", arg)) {
801 - /* later processing wants to have this at argv[1] */
802 - argv--;
803 - argc++;
804 - break;
805 - }
806 - if (*arg == '-')
807 - usage(builtin_grep_usage);
808 -
809 - /* First unrecognized non-option token */
810 - if (!opt.pattern_list) {
811 - append_grep_pattern(&opt, arg, "command line", 0,
812 - GREP_PATTERN);
813 - break;
814 - }
815 - else {
816 - /* We are looking at the first path or rev;
817 - * it is found at argv[1] after leaving the
818 - * loop.
819 - */
820 - argc++; argv--;
821 - break;
822 - }
766 + argc = parse_options(argc, argv, options, grep_usage,
767 + PARSE_OPT_KEEP_DASHDASH |
768 + PARSE_OPT_STOP_AT_NON_OPTION |
769 + PARSE_OPT_NO_INTERNAL_HELP);
770 +
771 + /* First unrecognized non-option token */
772 + if (argc > 0 && !opt.pattern_list) {
773 + append_grep_pattern(&opt, argv[0], "command line", 0,
774 + GREP_PATTERN);
775 + argv++;
776 + argc--;
777 }
778
779 if (opt.color && !opt.color_external)
@@ -831,7 +785,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
785 compile_grep_patterns(&opt);
786
787 /* Check revs and then paths */
834 - for (i = 1; i < argc; i++) {
788 + for (i = 0; i < argc; i++) {
789 const char *arg = argv[i];
790 unsigned char sha1[20];
791 /* Is it a rev? */
grep.h
+14 -14
@@ -61,23 +61,23 @@ struct grep_opt {
61 struct grep_expr *pattern_expression;
62 int prefix_length;
63 regex_t regexp;
64 - unsigned linenum:1;
65 - unsigned invert:1;
66 - unsigned status_only:1;
67 - unsigned name_only:1;
68 - unsigned unmatch_name_only:1;
69 - unsigned count:1;
70 - unsigned word_regexp:1;
71 - unsigned fixed:1;
72 - unsigned all_match:1;
64 + int linenum;
65 + int invert;
66 + int status_only;
67 + int name_only;
68 + int unmatch_name_only;
69 + int count;
70 + int word_regexp;
71 + int fixed;
72 + int all_match;
73 #define GREP_BINARY_DEFAULT 0
74 #define GREP_BINARY_NOMATCH 1
75 #define GREP_BINARY_TEXT 2
76 - unsigned binary:2;
77 - unsigned extended:1;
78 - unsigned relative:1;
79 - unsigned pathname:1;
80 - unsigned null_following_name:1;
76 + int binary;
77 + int extended;
78 + int relative;
79 + int pathname;
80 + int null_following_name;
81 int color;
82 char color_match[COLOR_MAXLEN];
83 const char *color_external;