Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/grep/util.c
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | struct parsec { | ||||
regmatch_t matches[MAX_MATCHES]; /* Matches made */ | regmatch_t matches[MAX_MATCHES]; /* Matches made */ | ||||
struct str ln; /* Current line */ | struct str ln; /* Current line */ | ||||
size_t lnstart; /* Position in line */ | size_t lnstart; /* Position in line */ | ||||
size_t matchidx; /* Latest match index */ | size_t matchidx; /* Latest match index */ | ||||
int printed; /* Metadata printed? */ | int printed; /* Metadata printed? */ | ||||
bool binary; /* Binary file? */ | bool binary; /* Binary file? */ | ||||
}; | }; | ||||
#ifdef WITH_INTERNAL_NOSPEC | |||||
static int litexec(const struct pat *pat, const char * string, | |||||
ngie: Spurious space after "char *". | |||||
size_t nmatch, regmatch_t pmatch[]); | |||||
#endif | |||||
static int procline(struct parsec *pc); | static int procline(struct parsec *pc); | ||||
static void printline(struct parsec *pc, int sep); | static void printline(struct parsec *pc, int sep); | ||||
static void printline_metadata(struct str *line, int sep); | static void printline_metadata(struct str *line, int sep); | ||||
bool | bool | ||||
file_matching(const char *fname) | file_matching(const char *fname) | ||||
{ | { | ||||
char *fname_base, *fname_buf; | char *fname_base, *fname_buf; | ||||
▲ Show 20 Lines • Show All 263 Lines • ▼ Show 20 Lines | if (c && !cflag && !lflag && !Lflag && | ||||
binbehave == BINFILE_BIN && f->binary && !qflag) | binbehave == BINFILE_BIN && f->binary && !qflag) | ||||
printf(getstr(8), fn); | printf(getstr(8), fn); | ||||
free(pc.ln.file); | free(pc.ln.file); | ||||
free(f); | free(f); | ||||
return (c); | return (c); | ||||
} | } | ||||
#ifdef WITH_INTERNAL_NOSPEC | |||||
/* | |||||
* Internal implementation of literal string search within a string, modeled | |||||
* after regexec(3), for use when the regex(3) implementation doesn't offer | |||||
* either REG_NOSPEC or REG_LITERAL. This does not apply in the default FreeBSD | |||||
Done Inline ActionsMight be worth extending this comment with info you have in the proposed commit message above (i.e. does not apply in default FreeBSD config, applies if built against libgnuregex or on non-FreeBSD OSes). emaste: Might be worth extending this comment with info you have in the proposed commit message above… | |||||
* config, but in other scenarios such as building against libgnuregex or on | |||||
* some non-FreeBSD OSes. | |||||
*/ | |||||
static int | |||||
litexec(const struct pat *pat, const char * string, size_t nmatch, | |||||
regmatch_t pmatch[]) | |||||
{ | |||||
char * (*strstr_fn)(const char *, const char *); | |||||
char *sub, *subject; | |||||
const char *search; | |||||
size_t idx, n, ofs, stringlen; | |||||
Done Inline ActionsOught not use _-prefixed variables, what about strstr_fn = strcasestr or such? emaste: Ought not use `_`-prefixed variables, what about `strstr_fn = strcasestr` or such? | |||||
Not Done Inline ActionsIt did indeed feel dirty, but for some reason I hadn't thought of a _fn suffix. kevans: It did indeed feel dirty, but for some reason I hadn't thought of a _fn suffix. | |||||
if (cflags & REG_ICASE) | |||||
strstr_fn = strcasestr; | |||||
else | |||||
strstr_fn = strstr; | |||||
idx = 0; | |||||
ofs = pmatch[0].rm_so; | |||||
stringlen = pmatch[0].rm_eo; | |||||
if (ofs >= stringlen) | |||||
return (REG_NOMATCH); | |||||
subject = strndup(string, stringlen); | |||||
if (subject == NULL) | |||||
return (REG_ESPACE); | |||||
for (n = 0; ofs < stringlen;) { | |||||
search = (subject + ofs); | |||||
if ((unsigned long)pat->len > strlen(search)) | |||||
break; | |||||
sub = strstr_fn(search, pat->pat); | |||||
/* | |||||
* Ignoring the empty string possibility due to context: grep optimizes | |||||
* for empty patterns and will never reach this point. | |||||
*/ | |||||
if (sub == NULL) | |||||
break; | |||||
++n; | |||||
/* Fill in pmatch if necessary */ | |||||
if (nmatch > 0) { | |||||
pmatch[idx].rm_so = ofs + (sub - search); | |||||
pmatch[idx].rm_eo = pmatch[idx].rm_so + pat->len; | |||||
if (++idx == nmatch) | |||||
break; | |||||
ofs = pmatch[idx].rm_so + 1; | |||||
} else | |||||
/* We only needed to know if we match or not */ | |||||
break; | |||||
} | |||||
free(subject); | |||||
if (n > 0 && nmatch > 0) | |||||
for (n = idx; n < nmatch; ++n) | |||||
pmatch[n].rm_so = pmatch[n].rm_eo = -1; | |||||
return (n > 0 ? 0 : REG_NOMATCH); | |||||
} | |||||
#endif /* WITH_INTERNAL_NOSPEC */ | |||||
#define iswword(x) (iswalnum((x)) || (x) == L'_') | #define iswword(x) (iswalnum((x)) || (x) == L'_') | ||||
/* | /* | ||||
* Processes a line comparing it with the specified patterns. Each pattern | * Processes a line comparing it with the specified patterns. Each pattern | ||||
* is looped to be compared along with the full string, saving each and every | * is looped to be compared along with the full string, saving each and every | ||||
* match, which is necessary to colorize the output and to count the | * match, which is necessary to colorize the output and to count the | ||||
* matches. The matching lines are passed to printline() to display the | * matches. The matching lines are passed to printline() to display the | ||||
* appropriate output. | * appropriate output. | ||||
Show All 34 Lines | while (st <= pc->ln.len) { | ||||
startm = matchidx; | startm = matchidx; | ||||
retry = 0; | retry = 0; | ||||
if (st > 0 && pc->ln.dat[st - 1] != fileeol) | if (st > 0 && pc->ln.dat[st - 1] != fileeol) | ||||
leflags |= REG_NOTBOL; | leflags |= REG_NOTBOL; | ||||
/* Loop to compare with all the patterns */ | /* Loop to compare with all the patterns */ | ||||
for (i = 0; i < patterns; i++) { | for (i = 0; i < patterns; i++) { | ||||
pmatch.rm_so = st; | pmatch.rm_so = st; | ||||
pmatch.rm_eo = pc->ln.len; | pmatch.rm_eo = pc->ln.len; | ||||
#ifdef WITH_INTERNAL_NOSPEC | |||||
if (grepbehave == GREP_FIXED) | |||||
r = litexec(&pattern[i], pc->ln.dat, 1, &pmatch); | |||||
else | |||||
#endif | |||||
#ifndef WITHOUT_FASTMATCH | #ifndef WITHOUT_FASTMATCH | ||||
if (fg_pattern[i].pattern) | if (fg_pattern[i].pattern) | ||||
r = fastexec(&fg_pattern[i], | r = fastexec(&fg_pattern[i], | ||||
pc->ln.dat, 1, &pmatch, leflags); | pc->ln.dat, 1, &pmatch, leflags); | ||||
else | else | ||||
#endif | #endif | ||||
r = regexec(&r_pattern[i], pc->ln.dat, 1, | r = regexec(&r_pattern[i], pc->ln.dat, 1, | ||||
&pmatch, leflags); | &pmatch, leflags); | ||||
Show All 27 Lines | #endif | ||||
* matched once, then we should try the pattern | * matched once, then we should try the pattern | ||||
* again after advancing just past the start of | * again after advancing just past the start of | ||||
* the earliest match. This allows the pattern | * the earliest match. This allows the pattern | ||||
* to match later on in the line and possibly | * to match later on in the line and possibly | ||||
* still match a whole word. | * still match a whole word. | ||||
*/ | */ | ||||
if (r == REG_NOMATCH && | if (r == REG_NOMATCH && | ||||
(retry == pc->lnstart || | (retry == pc->lnstart || | ||||
pmatch.rm_so + 1 < retry)) | (unsigned int)pmatch.rm_so + 1 < retry)) | ||||
kevansAuthorUnsubmitted Not Done Inline ActionsI forgot to update my working copy -- this will not be included since it already went in. kevans: I forgot to update my working copy -- this will not be included since it already went in. | |||||
retry = pmatch.rm_so + 1; | retry = pmatch.rm_so + 1; | ||||
if (r == REG_NOMATCH) | if (r == REG_NOMATCH) | ||||
continue; | continue; | ||||
} | } | ||||
lastmatches++; | lastmatches++; | ||||
lastmatch = pmatch; | lastmatch = pmatch; | ||||
if (matchidx == 0) | if (matchidx == 0) | ||||
▲ Show 20 Lines • Show All 216 Lines • Show Last 20 Lines |
Spurious space after "char *".