From 214be13d33a26ab45231afe8e983d9a174aae282 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 20 Dec 2016 08:56:06 -0800 Subject: [PATCH 2/3] grep: simplify matcher configuration * src/grep.c (matcher, compile): Remove static vars. (compile_fp_t): Now takes a 3rd syntax argument. (Gcomppile, Ecompile, Acompile, GAcompile, PAcompile): Remove. (struct matcher): Now nameless, since it is used only once. Make 'name' a bit shorter. New member 'syntax'. (matchers): Initialize it, and change removed functions to GEAcompile. (F_MATCHER_INDEX, G_MATCHER_INDEX): New constants. (setmatcher): New arg MATCHER, and return new matcher index. Avoid unnecessary call to strcmp. (main): Keep matcher as a local int, not a global pointer. * src/kwsearch.c (Fcompile): * src/pcresearch.c (Pcompile): Ignore the 3rd syntax argument. --- src/grep.c | 111 +++++++++++++++++++------------------------------------ src/kwsearch.c | 2 +- src/pcresearch.c | 2 +- src/search.h | 4 +- 4 files changed, 41 insertions(+), 78 deletions(-) diff --git a/src/grep.c b/src/grep.c index 76f83d5..574a380 100644 --- a/src/grep.c +++ b/src/grep.c @@ -491,8 +491,6 @@ bool match_words; bool match_lines; char eolbyte; -static char const *matcher; - /* For error messages. */ /* The input file name, or (if standard input) null or a --label argument. */ static char const *filename; @@ -577,9 +575,8 @@ static bool seek_failed; static bool seek_data_failed; /* Functions we'll use to search. */ -typedef void (*compile_fp_t) (char const *, size_t); +typedef void (*compile_fp_t) (char const *, size_t, reg_syntax_t); typedef size_t (*execute_fp_t) (char const *, size_t, size_t *, char const *); -static compile_fp_t compile; static execute_fp_t execute; static char const * @@ -2019,70 +2016,36 @@ if any error occurs and -q is not given, the exit status is 2.\n")); /* Pattern compilers and matchers. */ -static void -Gcompile (char const *pattern, size_t size) -{ - GEAcompile (pattern, size, RE_SYNTAX_GREP); -} - -static void -Ecompile (char const *pattern, size_t size) -{ - GEAcompile (pattern, size, RE_SYNTAX_EGREP); -} - -static void -Acompile (char const *pattern, size_t size) -{ - GEAcompile (pattern, size, RE_SYNTAX_AWK); -} - -static void -GAcompile (char const *pattern, size_t size) -{ - GEAcompile (pattern, size, RE_SYNTAX_GNU_AWK); -} - -static void -PAcompile (char const *pattern, size_t size) -{ - GEAcompile (pattern, size, RE_SYNTAX_POSIX_AWK); -} - -struct matcher +static struct { - char const name[16]; + char const name[12]; + int syntax; /* used if compile == GEAcompile */ compile_fp_t compile; execute_fp_t execute; +} const matchers[] = { + { "grep", RE_SYNTAX_GREP, GEAcompile, EGexecute }, + { "egrep", RE_SYNTAX_EGREP, GEAcompile, EGexecute }, + { "fgrep", 0, Fcompile, Fexecute, }, + { "awk", RE_SYNTAX_AWK, GEAcompile, EGexecute }, + { "gawk", RE_SYNTAX_GNU_AWK, GEAcompile, EGexecute }, + { "posixawk", RE_SYNTAX_POSIX_AWK, GEAcompile, EGexecute }, + { "perl", 0, Pcompile, Pexecute, }, }; -static struct matcher const matchers[] = { - { "grep", Gcompile, EGexecute }, - { "egrep", Ecompile, EGexecute }, - { "fgrep", Fcompile, Fexecute }, - { "awk", Acompile, EGexecute }, - { "gawk", GAcompile, EGexecute }, - { "posixawk", PAcompile, EGexecute }, - { "perl", Pcompile, Pexecute }, - { "", NULL, NULL }, -}; +/* Keep these in sync with the 'matchers' table. */ +enum { F_MATCHER_INDEX = 2, G_MATCHER_INDEX = 0 }; -/* Set the matcher to M if available. Exit in case of conflicts or if - M is not available. */ -static void -setmatcher (char const *m) +/* Return the index of the matcher corresponding to M if available. + MATCHER is the index of the previous matcher, or -1 if none. + Exit in case of conflicts or if M is not available. */ +static int +setmatcher (char const *m, int matcher) { - struct matcher const *p; - - if (matcher && !STREQ (matcher, m)) - die (EXIT_TROUBLE, 0, _("conflicting matchers specified")); - - for (p = matchers; p->compile; p++) - if (STREQ (m, p->name)) + for (int i = 0; i < sizeof matchers / sizeof *matchers; i++) + if (STREQ (m, matchers[i].name)) { - matcher = p->name; - compile = p->compile; - execute = p->execute; - return; + if (0 <= matcher && matcher != i) + die (EXIT_TROUBLE, 0, _("conflicting matchers specified")); + return i; } die (EXIT_TROUBLE, 0, _("invalid matcher %s"), m); @@ -2367,6 +2330,7 @@ main (int argc, char **argv) { char *keys = NULL; size_t keycc = 0, oldcc, keyalloc = 0; + int matcher = -1; bool with_filenames = false; size_t cc; int opt, prepended; @@ -2409,9 +2373,6 @@ main (int argc, char **argv) error (0, 0, _("warning: GREP_OPTIONS is deprecated;" " please use an alias or script")); - compile = matchers[0].compile; - execute = matchers[0].execute; - while (prev_optind = optind, (opt = get_nondigit_option (argc, argv, &default_context)) != -1) switch (opt) @@ -2440,23 +2401,23 @@ main (int argc, char **argv) break; case 'E': - setmatcher ("egrep"); + matcher = setmatcher ("egrep", matcher); break; case 'F': - setmatcher ("fgrep"); + matcher = setmatcher ("fgrep", matcher); break; case 'P': - setmatcher ("perl"); + matcher = setmatcher ("perl", matcher); break; case 'G': - setmatcher ("grep"); + matcher = setmatcher ("grep", matcher); break; case 'X': /* undocumented on purpose */ - setmatcher (optarg); + matcher = setmatcher (optarg, matcher); break; case 'H': @@ -2794,24 +2755,26 @@ main (int argc, char **argv) initialize_unibyte_mask (); + if (matcher < 0) + matcher = G_MATCHER_INDEX; + /* In a unibyte locale, switch from fgrep to grep if the pattern matches words (where grep is typically faster). In a multibyte locale, switch from fgrep to grep if either (1) the pattern has an encoding error (where fgrep might not work), or (2) case is ignored and a fast fgrep ignore-case is not available. */ - if (compile == Fcompile + if (matcher == F_MATCHER_INDEX && (MB_CUR_MAX <= 1 ? match_words : (contains_encoding_error (keys, keycc) || (match_icase && !fgrep_icase_available (keys, keycc))))) { fgrep_to_grep_pattern (&keys, &keycc); - matcher = "grep"; - compile = Gcompile; - execute = EGexecute; + matcher = G_MATCHER_INDEX; } - compile (keys, keycc); + execute = matchers[matcher].execute; + matchers[matcher].compile (keys, keycc, matchers[matcher].syntax); free (keys); /* We need one byte prior and one after. */ char eolbytes[3] = { 0, eolbyte, 0 }; diff --git a/src/kwsearch.c b/src/kwsearch.c index c3e69b3..7275973 100644 --- a/src/kwsearch.c +++ b/src/kwsearch.c @@ -34,7 +34,7 @@ wordchar (wint_t wc) static kwset_t kwset; void -Fcompile (char const *pattern, size_t size) +Fcompile (char const *pattern, size_t size, reg_syntax_t ignored) { size_t total = size; diff --git a/src/pcresearch.c b/src/pcresearch.c index 108baff..0e34861 100644 --- a/src/pcresearch.c +++ b/src/pcresearch.c @@ -88,7 +88,7 @@ static int empty_match[2]; #endif void -Pcompile (char const *pattern, size_t size) +Pcompile (char const *pattern, size_t size, reg_syntax_t ignored) { #if !HAVE_LIBPCRE die (EXIT_TROUBLE, 0, diff --git a/src/search.h b/src/search.h index 4957a63..1ff5be2 100644 --- a/src/search.h +++ b/src/search.h @@ -57,11 +57,11 @@ extern void GEAcompile (char const *, size_t, reg_syntax_t); extern size_t EGexecute (char const *, size_t, size_t *, char const *); /* kwsearch.c */ -extern void Fcompile (char const *, size_t); +extern void Fcompile (char const *, size_t, reg_syntax_t); extern size_t Fexecute (char const *, size_t, size_t *, char const *); /* pcresearch.c */ -extern void Pcompile (char const *, size_t); +extern void Pcompile (char const *, size_t, reg_syntax_t); extern size_t Pexecute (char const *, size_t, size_t *, char const *); /* Return the number of bytes in the character at the start of S, which -- 2.7.4