{"thread":{"id":"27245","subject":"[PATCH 1/3] grep: Put calls to fixmatch() and regmatch() into patmatch()","startedAt":"2011-05-03T21:35:55Z","lastAt":"2011-05-04T06:16:28Z","messageCount":6,"participants":["Michał Kiedrowicz","Junio C Hamano","Martin Langhoff","Michal Kiedrowicz"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"166971","messageId":"1304458557-25629-1-git-send-email-michal.kiedrowicz@gmail.com","threadId":"27245","inReplyTo":null,"subject":"[PATCH 1/3] grep: Put calls to fixmatch() and regmatch() into patmatch()","fromName":"Michał Kiedrowicz","fromEmail":"michal.kiedrowicz@gmail.com","sentAt":"2011-05-03T21:35:55Z","receivedAt":"2011-05-03T21:35:55Z","isPatch":true,"sender":{"key":"michal.kiedrowicz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14072847?v=4"},"body":"---\n grep.c |   23 +++++++++++++++--------\n 1 files changed, 15 insertions(+), 8 deletions(-)\n\ndiff --git a/grep.c b/grep.c\nindex 63c4280..d67baf9 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -412,6 +412,19 @@ static int regmatch(const regex_t *preg, char *line, char *eol,\n \treturn regexec(preg, line, 1, match, eflags);\n }\n \n+static int patmatch(struct grep_pat *p, char *line, char *eol,\n+\t\t    regmatch_t *match, int eflags)\n+{\n+\tint hit;\n+\n+\tif (p->fixed)\n+\t\thit = !fixmatch(p, line, eol, match);\n+\telse\n+\t\thit = !regmatch(&p->regexp, line, eol, match, eflags);\n+\n+\treturn hit;\n+}\n+\n static int strip_timestamp(char *bol, char **eol_p)\n {\n \tchar *eol = *eol_p;\n@@ -461,10 +474,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,\n \t}\n \n  again:\n-\tif (p->fixed)\n-\t\thit = !fixmatch(p, bol, eol, pmatch);\n-\telse\n-\t\thit = !regmatch(&p->regexp, bol, eol, pmatch, eflags);\n+\thit = patmatch(p, bol, eol, pmatch, eflags);\n \n \tif (hit && p->word_regexp) {\n \t\tif ((pmatch[0].rm_so < 0) ||\n@@ -791,10 +801,7 @@ static int look_ahead(struct grep_opt *opt,\n \t\tint hit;\n \t\tregmatch_t m;\n \n-\t\tif (p->fixed)\n-\t\t\thit = !fixmatch(p, bol, bol + *left_p, &m);\n-\t\telse\n-\t\t\thit = !regmatch(&p->regexp, bol, bol + *left_p, &m, 0);\n+\t\thit = patmatch(p, bol, bol + *left_p, &m, 0);\n \t\tif (!hit || m.rm_so < 0 || m.rm_eo < 0)\n \t\t\tcontinue;\n \t\tif (earliest < 0 || m.rm_so < earliest)\n-- \n1.7.3.4\n"},{"id":"166972","messageId":"1304458557-25629-2-git-send-email-michal.kiedrowicz@gmail.com","threadId":"27245","inReplyTo":"1304458557-25629-1-git-send-email-michal.kiedrowicz@gmail.com","subject":"[PATCH 2/3] Documentation: Add --line-number to git-grep synopsis","fromName":"Michał Kiedrowicz","fromEmail":"michal.kiedrowicz@gmail.com","sentAt":"2011-05-03T21:35:56Z","receivedAt":"2011-05-03T21:35:56Z","isPatch":true,"sender":{"key":"michal.kiedrowicz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14072847?v=4"},"body":"---\n Documentation/git-grep.txt |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt\nindex d7523b3..4a58378 100644\n--- a/Documentation/git-grep.txt\n+++ b/Documentation/git-grep.txt\n@@ -12,7 +12,7 @@ SYNOPSIS\n 'git grep' [-a | --text] [-I] [-i | --ignore-case] [-w | --word-regexp]\n \t   [-v | --invert-match] [-h|-H] [--full-name]\n \t   [-E | --extended-regexp] [-G | --basic-regexp]\n-\t   [-F | --fixed-strings] [-n]\n+\t   [-F | --fixed-strings] [-n | --line-number]\n \t   [-l | --files-with-matches] [-L | --files-without-match]\n \t   [(-O | --open-files-in-pager) [<pager>]]\n \t   [-z | --null]\n-- \n1.7.3.4\n"},{"id":"166973","messageId":"1304458557-25629-3-git-send-email-michal.kiedrowicz@gmail.com","threadId":"27245","inReplyTo":"1304458557-25629-1-git-send-email-michal.kiedrowicz@gmail.com","subject":"[RFC PATCH 3/3] git-grep: Learn PCRE","fromName":"Michał Kiedrowicz","fromEmail":"michal.kiedrowicz@gmail.com","sentAt":"2011-05-03T21:35:57Z","receivedAt":"2011-05-03T21:35:57Z","isPatch":true,"sender":{"key":"michal.kiedrowicz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14072847?v=4"},"body":"This is quite minimal (I hope) patch that teaches git-grep the\n--perl-regexp/-P options in order to allow specifying PCRE regexes on\nthe command line.\n\nPCRE has a number of features which make them more handy to use than\nPOSIX regexes, like consistent escaping rules, extended character\nclasses, ungreedy matching etc.\n\nHere are some implementation notes:\n\nNames of command line options are borrowed from GNU grep.\n\nMakefile changes are based on curl handing.\n\nThe configure script wasn't updated.\n\nThis patch lacks tests.\n\nAFAIK grep.c is a part of libgit.a, so libpcre is linked with the git\nitself, which bloats it. I don't like it, especially because it makes\n'make test' take:\n\n\treal    6m27.558s\n\tuser    1m34.392s\n\tsys     2m11.029s\n\ninstead of\n\n\treal    3m41.322s\n\tuser    1m44.005s\n\tsys     2m32.403s\n\non my PC.\n---\n Documentation/git-grep.txt |    6 ++++\n Makefile                   |   16 ++++++++++++\n builtin/grep.c             |    2 +\n grep.c                     |   57 ++++++++++++++++++++++++++++++++++++++++++++\n grep.h                     |    8 ++++++\n 5 files changed, 89 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt\nindex 4a58378..e150c77 100644\n--- a/Documentation/git-grep.txt\n+++ b/Documentation/git-grep.txt\n@@ -12,6 +12,7 @@ SYNOPSIS\n 'git grep' [-a | --text] [-I] [-i | --ignore-case] [-w | --word-regexp]\n \t   [-v | --invert-match] [-h|-H] [--full-name]\n \t   [-E | --extended-regexp] [-G | --basic-regexp]\n+\t   [-P | --perl-regexp]\n \t   [-F | --fixed-strings] [-n | --line-number]\n \t   [-l | --files-with-matches] [-L | --files-without-match]\n \t   [(-O | --open-files-in-pager) [<pager>]]\n@@ -97,6 +98,11 @@ OPTIONS\n \tUse POSIX extended/basic regexp for patterns.  Default\n \tis to use basic regexp.\n \n+-P::\n+--perl-regexp::\n+\tUse Perl-compatible regexp for patterns. Requires libpcre to be\n+\tcompiled in.\n+\n -F::\n --fixed-strings::\n \tUse fixed strings for patterns (don't interpret pattern\ndiff --git a/Makefile b/Makefile\nindex 3a1fe20..98841dc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -24,6 +24,12 @@ all::\n # Define NO_OPENSSL environment variable if you do not have OpenSSL.\n # This also implies BLK_SHA1.\n #\n+# Define NO_LIBPCRE if you do not have libpcre installed.  git-grep cannot use\n+# Perl-compatible regexes.\n+#\n+# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in\n+# /foo/bar/include and /foo/bar/lib directories.\n+#\n # Define NO_CURL if you do not have libcurl installed.  git-http-pull and\n # git-http-push are not built, and you cannot use http:// and https://\n # transports.\n@@ -1251,6 +1257,16 @@ ifdef NO_LIBGEN_H\n \tCOMPAT_OBJS += compat/basename.o\n endif\n \n+ifdef NO_LIBPCRE\n+\tBASIC_CFLAGS += -DNO_LIBPCRE\n+else\n+\tifdef LIBPCREDIR\n+\t\tBASIC_CFLAGS += -I$(LIBPCREDIR)/include\n+\t\tEXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)\n+\tendif\n+\tEXTLIBS += -lpcre\n+endif\n+\n ifdef NO_CURL\n \tBASIC_CFLAGS += -DNO_CURL\n \tREMOTE_CURL_PRIMARY =\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 10a1f65..6831975 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -781,6 +781,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\tREG_EXTENDED),\n \t\tOPT_BOOLEAN('F', \"fixed-strings\", &opt.fixed,\n \t\t\t\"interpret patterns as fixed strings\"),\n+\t\tOPT_BOOLEAN('P', \"perl-regexp\", &opt.pcre,\n+\t\t\t\t\"use Perl-compatible regular expressions\"),\n \t\tOPT_GROUP(\"\"),\n \t\tOPT_BOOLEAN('n', \"line-number\", &opt.linenum, \"show line numbers\"),\n \t\tOPT_NEGBIT('h', NULL, &opt.pathname, \"don't show filenames\", 1),\ndiff --git a/grep.c b/grep.c\nindex d67baf9..4f5fcbb 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -70,6 +70,30 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)\n \tif (p->fixed)\n \t\treturn;\n \n+\tif (opt->pcre) {\n+#ifdef NO_LIBPCRE\n+\t\tdie(\"cannot use Perl-compatible regexes when libpcre is not compiled in\");\n+#else\n+\t\tconst char *error;\n+\t\tint erroffset;\n+\t\tint options = 0;\n+\n+\t\tif (opt->ignore_case)\n+\t\t\toptions |= PCRE_CASELESS;\n+\n+\t\tp->re = pcre_compile(p->pattern, options, &error,\n+\t\t\t\t&erroffset, NULL);\n+\t\tif (!p->re)\n+\t\t\tdie(\"'%s': %s\", p->pattern, error);\n+\n+\t\tp->extra = pcre_study(p->re, 0, &error);\n+\t\tif (!p->extra && error)\n+\t\t\tdie(\"%s\", error);\n+\n+\t\treturn;\n+#endif\n+\t}\n+\n \terr = regcomp(&p->regexp, p->pattern, opt->regflags);\n \tif (err) {\n \t\tchar errbuf[1024];\n@@ -320,7 +344,16 @@ void free_grep_patterns(struct grep_opt *opt)\n \t\tcase GREP_PATTERN: /* atom */\n \t\tcase GREP_PATTERN_HEAD:\n \t\tcase GREP_PATTERN_BODY:\n+#ifndef NO_LIBPCRE\n+\t\t\tif (p->re) {\n+\t\t\t\tpcre_free(p->re);\n+\t\t\t\tpcre_free(p->extra);\n+\t\t\t} else {\n+\t\t\t\tregfree(&p->regexp);\n+\t\t\t}\n+#else\n \t\t\tregfree(&p->regexp);\n+#endif\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n@@ -401,6 +434,26 @@ static int fixmatch(struct grep_pat *p, char *line, char *eol,\n \t}\n }\n \n+#ifndef NO_LIBPCRE\n+static int pcrematch(const pcre *re, const pcre_extra *extra, char *line,\n+\t\tchar *eol, regmatch_t *match)\n+{\n+\tint ovector[30], ret;\n+\n+\tret = pcre_exec(re, NULL, line, eol - line, 0, 0, ovector,\n+\t\t\tARRAY_SIZE(ovector));\n+\tif (ret < 0 && ret != PCRE_ERROR_NOMATCH)\n+\t\tdie(\"pcre_exec failed with error code %d\", ret);\n+\tif (ret > 0) {\n+\t\tret = 0;\n+\t\tmatch->rm_so = ovector[0];\n+\t\tmatch->rm_eo = ovector[1];\n+\t}\n+\n+\treturn ret;\n+}\n+#endif /* NO_LIBPCRE */\n+\n static int regmatch(const regex_t *preg, char *line, char *eol,\n \t\t    regmatch_t *match, int eflags)\n {\n@@ -419,6 +472,10 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,\n \n \tif (p->fixed)\n \t\thit = !fixmatch(p, line, eol, match);\n+#ifndef NO_LIBPCRE\n+\telse if (p->re)\n+\t\thit = !pcrematch(p->re, p->extra, line, eol, match);\n+#endif /* NO_LIBPCRE */\n \telse\n \t\thit = !regmatch(&p->regexp, line, eol, match, eflags);\n \ndiff --git a/grep.h b/grep.h\nindex 06621fe..cd202a9 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -1,6 +1,9 @@\n #ifndef GREP_H\n #define GREP_H\n #include \"color.h\"\n+#ifndef NO_LIBPCRE\n+#include <pcre.h>\n+#endif /* NO_LIBPCRE */\n \n enum grep_pat_token {\n \tGREP_PATTERN,\n@@ -33,6 +36,10 @@ struct grep_pat {\n \tsize_t patternlen;\n \tenum grep_header_field field;\n \tregex_t regexp;\n+#ifndef NO_LIBPCRE\n+\tpcre *re;\n+\tpcre_extra *extra;\n+#endif /* NO_LIBPCRE */\n \tunsigned fixed:1;\n \tunsigned ignore_case:1;\n \tunsigned word_regexp:1;\n@@ -83,6 +90,7 @@ struct grep_opt {\n #define GREP_BINARY_TEXT\t2\n \tint binary;\n \tint extended;\n+\tint pcre;\n \tint relative;\n \tint pathname;\n \tint null_following_name;\n-- \n1.7.3.4\n"},{"id":"166976","messageId":"7vliyngz1x.fsf@alter.siamese.dyndns.org","threadId":"27245","inReplyTo":"1304458557-25629-3-git-send-email-michal.kiedrowicz@gmail.com","subject":"Re: [RFC PATCH 3/3] git-grep: Learn PCRE","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-03T23:11:06Z","receivedAt":"2011-05-03T23:11:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michał Kiedrowicz <michal.kiedrowicz@gmail.com> writes:\n\n> This patch lacks tests.\n>\n> AFAIK grep.c is a part of libgit.a, so libpcre is linked with the git\n> itself, which bloats it. I don't like it, especially because it makes\n> 'make test' take:\n>\n> \treal    6m27.558s\n> \tuser    1m34.392s\n> \tsys     2m11.029s\n>\n> instead of\n>\n> \treal    3m41.322s\n> \tuser    1m44.005s\n> \tsys     2m32.403s\n>\n> on my PC.\n\nI am not against pcre, but the performance numbers look rather yucky.\n\n> diff --git a/grep.c b/grep.c\n> index d67baf9..4f5fcbb 100644\n> --- a/grep.c\n> +++ b/grep.c\n> @@ -70,6 +70,30 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)\n>  \tif (p->fixed)\n>  \t\treturn;\n>  \n> +\tif (opt->pcre) {\n> +#ifdef NO_LIBPCRE\n> +\t\tdie(\"cannot use Perl-compatible regexes when libpcre is not compiled in\");\n> +#else\n> +\t\tconst char *error;\n> +\t...\n> +\t\treturn;\n> +#endif\n> +\t}\n> +\n\nPlease avoid these #ifdefs in the middle of otherwise generic function.\n\nMake the above into something like:\n\n\tif (opt->pcre) {\n        \tcompile_pcre(p, opt);\n                return;\n\t}\n\nand then have an extra section entirely devoted to pcre integration that\nhas bunch of ...\n\n        #ifdef NO_LIBPCRE\n        static void compile_pcre_part(struct grep_pat *p, struct grep_opt *opt)\n        {\n                die(\"...\");\n\t}\n        #else\n        static void compile_pcre_part(struct grep_pat *p, struct grep_opt *opt)\n        {\n                ...\n\t}\n        #endif\n\n... that is totally separate from the generic part of the codebase.  They\ncould even be in a separate file, if you need numerous helpers.\n\n> @@ -320,7 +344,16 @@ void free_grep_patterns(struct grep_opt *opt)\n>  \t\tcase GREP_PATTERN: /* atom */\n>  \t\tcase GREP_PATTERN_HEAD:\n>  \t\tcase GREP_PATTERN_BODY:\n> +#ifndef NO_LIBPCRE\n> +\t\t\tif (p->re) {\n> +\t\t\t\tpcre_free(p->re);\n> +\t\t\t\tpcre_free(p->extra);\n> +\t\t\t} else {\n> +\t\t\t\tregfree(&p->regexp);\n> +\t\t\t}\n> +#else\n>  \t\t\tregfree(&p->regexp);\n> +#endif\n>  \t\t\tbreak;\n>  \t\tdefault:\n>  \t\t\tbreak;\n\n> diff --git a/grep.h b/grep.h\n> index 06621fe..cd202a9 100644\n> --- a/grep.h\n> +++ b/grep.h\n> @@ -1,6 +1,9 @@\n>  #ifndef GREP_H\n>  #define GREP_H\n>  #include \"color.h\"\n> +#ifndef NO_LIBPCRE\n> +#include <pcre.h>\n> +#endif /* NO_LIBPCRE */\n\nThis part might want to do something like\n\n\t#ifndef NO_LIBPCRE\n        #include <pcre.h>\n        #else\n        typedef int pcre; /* dummy */\n        typedef int pcre_extra; /* dummy */\n        #endif\n\nif it makes it easier to keep the generic part of the code and structure\ndefinition clean.\n\nFor example, the \"free\" part of your patch above then would become\n\n\tif (p->pcre_regexp)\n        \tfree_pcre_part(p);\n\telse\n        \tregfree(&p->regexp);\n\nwith the conditional enclosed entirely within the implementation of\nthe free_pcre_part() helper function.\n\nAlso by doing so, the struct definition below can lose #ifndef, and can become:\n\n\t struct grep_pat {\n         ...\n        +\tpcre *pcre_regexp;\n        +\tpcre_extra *pcre_extra_info;\n\t ...\n\t };\n\n> @@ -33,6 +36,10 @@ struct grep_pat {\n>  \tsize_t patternlen;\n>  \tenum grep_header_field field;\n>  \tregex_t regexp;\n> +#ifndef NO_LIBPCRE\n> +\tpcre *re;\n> +\tpcre_extra *extra;\n> +#endif /* NO_LIBPCRE */\n>  \tunsigned fixed:1;\n>  \tunsigned ignore_case:1;\n>  \tunsigned word_regexp:1;\n> @@ -83,6 +90,7 @@ struct grep_opt {\n>  #define GREP_BINARY_TEXT\t2\n>  \tint binary;\n>  \tint extended;\n> +\tint pcre;\n>  \tint relative;\n>  \tint pathname;\n>  \tint null_following_name;\n"},{"id":"166977","messageId":"BANLkTimcj7do9=+PZ0=5+gBth59Ti5UxZA@mail.gmail.com","threadId":"27245","inReplyTo":"1304458557-25629-3-git-send-email-michal.kiedrowicz@gmail.com","subject":"Re: [RFC PATCH 3/3] git-grep: Learn PCRE","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2011-05-03T23:15:00Z","receivedAt":"2011-05-03T23:15:00Z","isPatch":true,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"2011/5/3 Michał Kiedrowicz <michal.kiedrowicz@gmail.com>:\n> This is quite minimal (I hope) patch that teaches git-grep the\n> --perl-regexp/-P options in order to allow specifying PCRE regexes on\n> the command line.\n\nOh joy!\n\n\n\nm\n-- \n martin.langhoff@gmail.com\n martin@laptop.org -- Software Architect - OLPC\n - ask interesting questions\n - don't get distracted with shiny stuff  - working code first\n - http://wiki.laptop.org/go/User:Martinlanghoff\n"},{"id":"166994","messageId":"20110504081628.6a80f4a0@mkiedrowicz","threadId":"27245","inReplyTo":"7vliyngz1x.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC PATCH 3/3] git-grep: Learn PCRE","fromName":"Michal Kiedrowicz","fromEmail":"michal.kiedrowicz@gmail.com","sentAt":"2011-05-04T06:16:28Z","receivedAt":"2011-05-04T06:16:28Z","isPatch":true,"sender":{"key":"michal.kiedrowicz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/14072847?v=4"},"body":"On 03.05.2011 16:11:06 -0700 Junio C Hamano <gitster@pobox.com> wrote:\n\n> Michał Kiedrowicz <michal.kiedrowicz@gmail.com> writes:\n> \n> > This patch lacks tests.\n> >\n> > AFAIK grep.c is a part of libgit.a, so libpcre is linked with the\n> > git itself, which bloats it. I don't like it, especially because it\n> > makes 'make test' take:\n> >\n> > \treal    6m27.558s\n> > \tuser    1m34.392s\n> > \tsys     2m11.029s\n> >\n> > instead of\n> >\n> > \treal    3m41.322s\n> > \tuser    1m44.005s\n> > \tsys     2m32.403s\n> >\n> > on my PC.\n> \n> I am not against pcre, but the performance numbers look rather yucky.\n> \n> > diff --git a/grep.c b/grep.c\n> > index d67baf9..4f5fcbb 100644\n> > --- a/grep.c\n> > +++ b/grep.c\n> > @@ -70,6 +70,30 @@ static void compile_regexp(struct grep_pat *p,\n> > struct grep_opt *opt) if (p->fixed)\n> >  \t\treturn;\n> >  \n> > +\tif (opt->pcre) {\n> > +#ifdef NO_LIBPCRE\n> > +\t\tdie(\"cannot use Perl-compatible regexes when\n> > libpcre is not compiled in\"); +#else\n> > +\t\tconst char *error;\n> > +\t...\n> > +\t\treturn;\n> > +#endif\n> > +\t}\n> > +\n> \n> Please avoid these #ifdefs in the middle of otherwise generic\n> function.\n\nYeah, I don't like them too.\n\n> \n> Make the above into something like:\n> \n> \tif (opt->pcre) {\n>         \tcompile_pcre(p, opt);\n>                 return;\n> \t}\n> \n> and then have an extra section entirely devoted to pcre integration\n> that has bunch of ...\n> \n>         #ifdef NO_LIBPCRE\n>         static void compile_pcre_part(struct grep_pat *p, struct\n> grep_opt *opt) {\n>                 die(\"...\");\n> \t}\n>         #else\n>         static void compile_pcre_part(struct grep_pat *p, struct\n> grep_opt *opt) {\n>                 ...\n> \t}\n>         #endif\n> \n> ... that is totally separate from the generic part of the codebase.\n> They could even be in a separate file, if you need numerous helpers.\n> \n> > @@ -320,7 +344,16 @@ void free_grep_patterns(struct grep_opt *opt)\n> >  \t\tcase GREP_PATTERN: /* atom */\n> >  \t\tcase GREP_PATTERN_HEAD:\n> >  \t\tcase GREP_PATTERN_BODY:\n> > +#ifndef NO_LIBPCRE\n> > +\t\t\tif (p->re) {\n> > +\t\t\t\tpcre_free(p->re);\n> > +\t\t\t\tpcre_free(p->extra);\n> > +\t\t\t} else {\n> > +\t\t\t\tregfree(&p->regexp);\n> > +\t\t\t}\n> > +#else\n> >  \t\t\tregfree(&p->regexp);\n> > +#endif\n> >  \t\t\tbreak;\n> >  \t\tdefault:\n> >  \t\t\tbreak;\n> \n> > diff --git a/grep.h b/grep.h\n> > index 06621fe..cd202a9 100644\n> > --- a/grep.h\n> > +++ b/grep.h\n> > @@ -1,6 +1,9 @@\n> >  #ifndef GREP_H\n> >  #define GREP_H\n> >  #include \"color.h\"\n> > +#ifndef NO_LIBPCRE\n> > +#include <pcre.h>\n> > +#endif /* NO_LIBPCRE */\n> \n> This part might want to do something like\n> \n> \t#ifndef NO_LIBPCRE\n>         #include <pcre.h>\n>         #else\n>         typedef int pcre; /* dummy */\n>         typedef int pcre_extra; /* dummy */\n>         #endif\n> \n> if it makes it easier to keep the generic part of the code and\n> structure definition clean.\n> \n> For example, the \"free\" part of your patch above then would become\n> \n> \tif (p->pcre_regexp)\n>         \tfree_pcre_part(p);\n> \telse\n>         \tregfree(&p->regexp);\n> \n> with the conditional enclosed entirely within the implementation of\n> the free_pcre_part() helper function.\n> \n> Also by doing so, the struct definition below can lose #ifndef, and\n> can become:\n> \n> \t struct grep_pat {\n>          ...\n>         +\tpcre *pcre_regexp;\n>         +\tpcre_extra *pcre_extra_info;\n> \t ...\n> \t };\n\nThat makes sense. Will re-roll (and add Signed-off-by).\n\n> \n> > @@ -33,6 +36,10 @@ struct grep_pat {\n> >  \tsize_t patternlen;\n> >  \tenum grep_header_field field;\n> >  \tregex_t regexp;\n> > +#ifndef NO_LIBPCRE\n> > +\tpcre *re;\n> > +\tpcre_extra *extra;\n> > +#endif /* NO_LIBPCRE */\n> >  \tunsigned fixed:1;\n> >  \tunsigned ignore_case:1;\n> >  \tunsigned word_regexp:1;\n> > @@ -83,6 +90,7 @@ struct grep_opt {\n> >  #define GREP_BINARY_TEXT\t2\n> >  \tint binary;\n> >  \tint extended;\n> > +\tint pcre;\n> >  \tint relative;\n> >  \tint pathname;\n> >  \tint null_following_name;\n"}]}