#include "cache.h"
#include "grep.h"
#include "userdiff.h"
#include "xdiff-interface.h"
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
{
struct grep_pat *p = xcalloc(1, sizeof(*p));
p->pattern = pat;
p->patternlen = strlen(pat);
p->origin = "header";
p->no = 0;
p->token = GREP_PATTERN_HEAD;
p->field = field;
*opt->header_tail = p;
opt->header_tail = &p->next;
p->next = NULL;
}
void append_grep_pattern(struct grep_opt *opt, const char *pat,
const char *origin, int no, enum grep_pat_token t)
{
append_grep_pat(opt, pat, strlen(pat), origin, no, t);
}
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
const char *origin, int no, enum grep_pat_token t)
{
struct grep_pat *p = xcalloc(1, sizeof(*p));
p->pattern = pat;
p->patternlen = patlen;
p->origin = origin;
p->no = no;
p->token = t;
*opt->pattern_tail = p;
opt->pattern_tail = &p->next;
p->next = NULL;
}
struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
{
struct grep_pat *pat;
struct grep_opt *ret = xmalloc(sizeof(struct grep_opt));
*ret = *opt;
ret->pattern_list = NULL;
ret->pattern_tail = &ret->pattern_list;
for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
{
if(pat->token == GREP_PATTERN_HEAD)
append_header_grep_pattern(ret, pat->field,
pat->pattern);
else
append_grep_pat(ret, pat->pattern, pat->patternlen,
pat->origin, pat->no, pat->token);
}
return ret;
}
static NORETURN void compile_regexp_failed(const struct grep_pat *p,
const char *error)
{
char where[1024];
if (p->no)
sprintf(where, "In '%s' at %d, ", p->origin, p->no);
else if (p->origin)
sprintf(where, "%s, ", p->origin);
else
where[0] = 0;
die("%s'%s': %s", where, p->pattern, error);
}
#ifdef USE_LIBPCRE
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
{
const char *error;
int erroffset;
int options = 0;
if (opt->ignore_case)
options |= PCRE_CASELESS;
p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
NULL);
if (!p->pcre_regexp)
compile_regexp_failed(p, error);
p->pcre_extra_info = pcre_study(p->pcre_regexp, 0, &error);
if (!p->pcre_extra_info && error)
die("%s", error);
}
static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
regmatch_t *match, int eflags)
{
int ovector[30], ret, flags = 0;
if (eflags & REG_NOTBOL)
flags |= PCRE_NOTBOL;
ret = pcre_exec(p->pcre_regexp, p->pcre_extra_info, line, eol - line,
0, flags, ovector, ARRAY_SIZE(ovector));
if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
die("pcre_exec failed with error code %d", ret);
if (ret > 0) {
ret = 0;
match->rm_so = ovector[0];
match->rm_eo = ovector[1];
}
return ret;
}
static void free_pcre_regexp(struct grep_pat *p)
{
pcre_free(p->pcre_regexp);
pcre_free(p->pcre_extra_info);
}
#else /* !USE_LIBPCRE */
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
{
die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
}
static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
regmatch_t *match, int eflags)
{
return 1;
}
static void free_pcre_regexp(struct grep_pat *p)
{
}
#endif /* !USE_LIBPCRE */
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{
int err;
p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case;
p->fixed = opt->fixed;
if (p->fixed)
return;
if (opt->pcre) {
compile_pcre_regexp(p, opt);
return;
}
err = regcomp(&p->regexp, p->pattern, opt->regflags);
if (err) {
char errbuf[1024];
regerror(err, &p->regexp, errbuf, 1024);
regfree(&p->regexp);
compile_regexp_failed(p, errbuf);
}
}
static struct grep_expr *compile_pattern_or(struct grep_pat **);
static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
{
struct grep_pat *p;
struct grep_expr *x;
p = *list;
if (!p)
|