p->next = NULL;
}
+static int isregexspecial(int c)
+{
+ return isspecial(c) || c == '$' || c == '(' || c == ')' || c == '+' ||
+ c == '.' || c == '^' || c == '{' || c == '|';
+}
+
+static int is_fixed(const char *s)
+{
+ while (!isregexspecial(*s))
+ s++;
+ return !*s;
+}
+
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{
- int err = regcomp(&p->regexp, p->pattern, opt->regflags);
+ int err;
+
+ if (opt->fixed || is_fixed(p->pattern))
+ p->fixed = 1;
+ if (opt->regflags & REG_ICASE)
+ p->fixed = 0;
+ if (p->fixed)
+ return;
+
+ err = regcomp(&p->regexp, p->pattern, opt->regflags);
if (err) {
char errbuf[1024];
char where[1024];
case GREP_PATTERN: /* atom */
case GREP_PATTERN_HEAD:
case GREP_PATTERN_BODY:
- if (!opt->fixed)
- compile_regexp(p, opt);
+ compile_regexp(p, opt);
break;
default:
opt->extended = 1;
static void show_line(struct grep_opt *opt, const char *bol, const char *eol,
const char *name, unsigned lno, char sign)
{
+ if (opt->null_following_name)
+ sign = '\0';
if (opt->pathname)
printf("%s%c", name, sign);
if (opt->linenum)
printf("%.*s\n", (int)(eol-bol), bol);
}
+static void show_name(struct grep_opt *opt, const char *name)
+{
+ printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
+}
+
static int fixmatch(const char *pattern, char *line, regmatch_t *match)
{
char *hit = strstr(line, pattern);
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
{
int hit = 0;
- int at_true_bol = 1;
int saved_ch = 0;
regmatch_t pmatch[10];
}
again:
- if (!opt->fixed) {
+ if (!p->fixed) {
regex_t *exp = &p->regexp;
hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
pmatch, 0);
* either end of the line, or at word boundary
* (i.e. the next char must not be a word char).
*/
- if ( ((pmatch[0].rm_so == 0 && at_true_bol) ||
+ if ( ((pmatch[0].rm_so == 0) ||
!word_char(bol[pmatch[0].rm_so-1])) &&
((pmatch[0].rm_eo == (eol-bol)) ||
!word_char(bol[pmatch[0].rm_eo])) )
/* There could be more than one match on the
* line, and the first match might not be
* strict word match. But later ones could be!
+ * Forward to the next possible start, i.e. the
+ * next position following a non-word char.
*/
bol = pmatch[0].rm_so + bol + 1;
- at_true_bol = 0;
- goto again;
+ while (word_char(bol[-1]) && bol < eol)
+ bol++;
+ if (bol < eol)
+ goto again;
}
}
if (p->token == GREP_PATTERN_HEAD && saved_ch)
h |= match_expr_eval(o, x->u.binary.right, bol, eol, ctx, 1);
break;
default:
- die("Unexpected node type (internal error) %d\n", x->node);
+ die("Unexpected node type (internal error) %d", x->node);
}
if (collect_hits)
x->hit |= h;
return 1;
}
if (opt->name_only) {
- printf("%s\n", name);
+ show_name(opt, name);
return 1;
}
/* Hit at this line. If we haven't shown the
return 0;
if (opt->unmatch_name_only) {
/* We did not see any hit, so we want to show this */
- printf("%s\n", name);
+ show_name(opt, name);
return 1;
}
* make it another option? For now suppress them.
*/
if (opt->count && count)
- printf("%s:%u\n", name, count);
+ printf("%s%c%u\n", name,
+ opt->null_following_name ? '\0' : ':', count);
return !!last_hit;
}