version 1.5, 2014/05/28 11:39:15 |
version 1.6, 2015/11/05 22:08:44 |
|
|
* |
* |
* For more information, see the README file. |
* For more information, see the README file. |
*/ |
*/ |
|
/* |
|
* Modified for use with illumos. |
|
* Copyright 2014 Garrett D'Amore <garrett@damore.org> |
|
*/ |
|
|
/* |
/* |
* Routines to do pattern matching. |
* Routines to do pattern matching. |
|
|
/* |
/* |
* Compile a search pattern, for future use by match_pattern. |
* Compile a search pattern, for future use by match_pattern. |
*/ |
*/ |
static int |
static int |
compile_pattern2(pattern, search_type, comp_pattern) |
compile_pattern2(char *pattern, int search_type, regex_t **comp_pattern) |
char *pattern; |
|
int search_type; |
|
void **comp_pattern; |
|
{ |
{ |
|
regex_t *comp; |
|
|
if (search_type & SRCH_NO_REGEX) |
if (search_type & SRCH_NO_REGEX) |
return (0); |
return (0); |
{ |
comp = ecalloc(1, sizeof (regex_t)); |
#if HAVE_GNU_REGEX |
if (regcomp(comp, pattern, less_is_more ? 0 : REGCOMP_FLAG)) { |
struct re_pattern_buffer *comp = (struct re_pattern_buffer *) |
|
ecalloc(1, sizeof(struct re_pattern_buffer)); |
|
struct re_pattern_buffer **pcomp = |
|
(struct re_pattern_buffer **) comp_pattern; |
|
re_set_syntax(RE_SYNTAX_POSIX_EXTENDED); |
|
if (re_compile_pattern(pattern, strlen(pattern), comp)) |
|
{ |
|
free(comp); |
free(comp); |
error("Invalid pattern", NULL_PARG); |
error("Invalid pattern", NULL_PARG); |
return (-1); |
return (-1); |
} |
} |
if (*pcomp != NULL) |
if (*comp_pattern != NULL) |
regfree(*pcomp); |
regfree(*comp_pattern); |
*pcomp = comp; |
*comp_pattern = comp; |
#endif |
|
#if HAVE_POSIX_REGCOMP |
|
regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t)); |
|
regex_t **pcomp = (regex_t **) comp_pattern; |
|
if (regcomp(comp, pattern, less_is_more ? 0 : REGCOMP_FLAG)) |
|
{ |
|
free(comp); |
|
error("Invalid pattern", NULL_PARG); |
|
return (-1); |
|
} |
|
if (*pcomp != NULL) |
|
regfree(*pcomp); |
|
*pcomp = comp; |
|
#endif |
|
#if HAVE_PCRE |
|
pcre *comp; |
|
pcre **pcomp = (pcre **) comp_pattern; |
|
constant char *errstring; |
|
int erroffset; |
|
PARG parg; |
|
comp = pcre_compile(pattern, 0, |
|
&errstring, &erroffset, NULL); |
|
if (comp == NULL) |
|
{ |
|
parg.p_string = (char *) errstring; |
|
error("%s", &parg); |
|
return (-1); |
|
} |
|
*pcomp = comp; |
|
#endif |
|
#if HAVE_RE_COMP |
|
PARG parg; |
|
int *pcomp = (int *) comp_pattern; |
|
if ((parg.p_string = re_comp(pattern)) != NULL) |
|
{ |
|
error("%s", &parg); |
|
return (-1); |
|
} |
|
*pcomp = 1; |
|
#endif |
|
#if HAVE_REGCMP |
|
char *comp; |
|
char **pcomp = (char **) comp_pattern; |
|
if ((comp = regcmp(pattern, 0)) == NULL) |
|
{ |
|
error("Invalid pattern", NULL_PARG); |
|
return (-1); |
|
} |
|
if (pcomp != NULL) |
|
free(*pcomp); |
|
*pcomp = comp; |
|
#endif |
|
#if HAVE_V8_REGCOMP |
|
struct regexp *comp; |
|
struct regexp **pcomp = (struct regexp **) comp_pattern; |
|
if ((comp = regcomp(pattern)) == NULL) |
|
{ |
|
/* |
|
* regcomp has already printed an error message |
|
* via regerror(). |
|
*/ |
|
return (-1); |
|
} |
|
if (*pcomp != NULL) |
|
free(*pcomp); |
|
*pcomp = comp; |
|
#endif |
|
} |
|
return (0); |
return (0); |
} |
} |
|
|
/* |
/* |
* Like compile_pattern2, but convert the pattern to lowercase if necessary. |
* Like compile_pattern2, but convert the pattern to lowercase if necessary. |
*/ |
*/ |
public int |
int |
compile_pattern(pattern, search_type, comp_pattern) |
compile_pattern(char *pattern, int search_type, regex_t **comp_pattern) |
char *pattern; |
|
int search_type; |
|
void **comp_pattern; |
|
{ |
{ |
char *cvt_pattern; |
char *cvt_pattern; |
int result; |
int result; |
|
|
if (caseless != OPT_ONPLUS && (caseless != OPT_ON || !less_is_more)) |
if (caseless != OPT_ONPLUS) { |
cvt_pattern = pattern; |
cvt_pattern = pattern; |
else |
} else { |
{ |
cvt_pattern = ecalloc(1, cvt_length(strlen(pattern))); |
cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC)); |
cvt_text(cvt_pattern, pattern, NULL, NULL, CVT_TO_LC); |
cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC); |
|
} |
} |
result = compile_pattern2(cvt_pattern, search_type, comp_pattern); |
result = compile_pattern2(cvt_pattern, search_type, comp_pattern); |
if (cvt_pattern != pattern) |
if (cvt_pattern != pattern) |
|
|
/* |
/* |
* Forget that we have a compiled pattern. |
* Forget that we have a compiled pattern. |
*/ |
*/ |
public void |
void |
uncompile_pattern(pattern) |
uncompile_pattern(regex_t **pattern) |
void **pattern; |
|
{ |
{ |
#if HAVE_GNU_REGEX |
if (*pattern != NULL) |
struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern; |
regfree(*pattern); |
if (*pcomp != NULL) |
*pattern = NULL; |
regfree(*pcomp); |
|
*pcomp = NULL; |
|
#endif |
|
#if HAVE_POSIX_REGCOMP |
|
regex_t **pcomp = (regex_t **) pattern; |
|
if (*pcomp != NULL) |
|
regfree(*pcomp); |
|
*pcomp = NULL; |
|
#endif |
|
#if HAVE_PCRE |
|
pcre **pcomp = (pcre **) pattern; |
|
if (*pcomp != NULL) |
|
pcre_free(*pcomp); |
|
*pcomp = NULL; |
|
#endif |
|
#if HAVE_RE_COMP |
|
int *pcomp = (int *) pattern; |
|
*pcomp = 0; |
|
#endif |
|
#if HAVE_REGCMP |
|
char **pcomp = (char **) pattern; |
|
if (*pcomp != NULL) |
|
free(*pcomp); |
|
*pcomp = NULL; |
|
#endif |
|
#if HAVE_V8_REGCOMP |
|
struct regexp **pcomp = (struct regexp **) pattern; |
|
if (*pcomp != NULL) |
|
free(*pcomp); |
|
*pcomp = NULL; |
|
#endif |
|
} |
} |
|
|
/* |
/* |
* Is a compiled pattern null? |
* Is a compiled pattern null? |
*/ |
*/ |
public int |
int |
is_null_pattern(pattern) |
is_null_pattern(void *pattern) |
void *pattern; |
|
{ |
{ |
#if HAVE_GNU_REGEX |
|
return (pattern == NULL); |
return (pattern == NULL); |
#endif |
|
#if HAVE_POSIX_REGCOMP |
|
return (pattern == NULL); |
|
#endif |
|
#if HAVE_PCRE |
|
return (pattern == NULL); |
|
#endif |
|
#if HAVE_RE_COMP |
|
return (pattern == 0); |
|
#endif |
|
#if HAVE_REGCMP |
|
return (pattern == NULL); |
|
#endif |
|
#if HAVE_V8_REGCOMP |
|
return (pattern == NULL); |
|
#endif |
|
} |
} |
|
|
/* |
/* |
* Simple pattern matching function. |
* Simple pattern matching function. |
* It supports no metacharacters like *, etc. |
* It supports no metacharacters like *, etc. |
*/ |
*/ |
static int |
static int |
match(pattern, pattern_len, buf, buf_len, pfound, pend) |
match(char *pattern, int pattern_len, char *buf, int buf_len, |
char *pattern; |
char **pfound, char **pend) |
int pattern_len; |
|
char *buf; |
|
int buf_len; |
|
char **pfound, **pend; |
|
{ |
{ |
register char *pp, *lp; |
char *pp, *lp; |
register char *pattern_end = pattern + pattern_len; |
char *pattern_end = pattern + pattern_len; |
register char *buf_end = buf + buf_len; |
char *buf_end = buf + buf_len; |
|
|
for ( ; buf < buf_end; buf++) |
for (; buf < buf_end; buf++) { |
{ |
for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++) |
for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++) |
|
if (pp == pattern_end || lp == buf_end) |
if (pp == pattern_end || lp == buf_end) |
break; |
break; |
if (pp == pattern_end) |
if (pp == pattern_end) { |
{ |
|
if (pfound != NULL) |
if (pfound != NULL) |
*pfound = buf; |
*pfound = buf; |
if (pend != NULL) |
if (pend != NULL) |
|
|
* Perform a pattern match with the previously compiled pattern. |
* Perform a pattern match with the previously compiled pattern. |
* Set sp and ep to the start and end of the matched string. |
* Set sp and ep to the start and end of the matched string. |
*/ |
*/ |
public int |
int |
match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type) |
match_pattern(void *pattern, char *tpattern, char *line, int line_len, |
void *pattern; |
char **sp, char **ep, int notbol, int search_type) |
char *tpattern; |
|
char *line; |
|
int line_len; |
|
char **sp; |
|
char **ep; |
|
int notbol; |
|
int search_type; |
|
{ |
{ |
int matched; |
int matched; |
#if HAVE_GNU_REGEX |
regex_t *spattern = (regex_t *)pattern; |
struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern; |
|
#endif |
|
#if HAVE_POSIX_REGCOMP |
|
regex_t *spattern = (regex_t *) pattern; |
|
#endif |
|
#if HAVE_PCRE |
|
pcre *spattern = (pcre *) pattern; |
|
#endif |
|
#if HAVE_RE_COMP |
|
int spattern = (int) pattern; |
|
#endif |
|
#if HAVE_REGCMP |
|
char *spattern = (char *) pattern; |
|
#endif |
|
#if HAVE_V8_REGCOMP |
|
struct regexp *spattern = (struct regexp *) pattern; |
|
#endif |
|
|
|
#if NO_REGEX |
if (search_type & SRCH_NO_REGEX) { |
search_type |= SRCH_NO_REGEX; |
matched = match(tpattern, strlen(tpattern), line, line_len, |
#endif |
sp, ep); |
if (search_type & SRCH_NO_REGEX) |
} else { |
matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep); |
|
else |
|
{ |
|
#if HAVE_GNU_REGEX |
|
{ |
|
struct re_registers search_regs; |
|
regoff_t *starts = (regoff_t *) ecalloc(1, sizeof (regoff_t)); |
|
regoff_t *ends = (regoff_t *) ecalloc(1, sizeof (regoff_t)); |
|
spattern->not_bol = notbol; |
|
re_set_registers(spattern, &search_regs, 1, starts, ends); |
|
matched = re_search(spattern, line, line_len, 0, line_len, &search_regs) >= 0; |
|
if (matched) |
|
{ |
|
*sp = line + search_regs.start[0]; |
|
*ep = line + search_regs.end[0]; |
|
} |
|
free(starts); |
|
free(ends); |
|
} |
|
#endif |
|
#if HAVE_POSIX_REGCOMP |
|
{ |
|
regmatch_t rm; |
regmatch_t rm; |
int flags = (notbol) ? REG_NOTBOL : 0; |
int flags = (notbol) ? REG_NOTBOL : 0; |
#ifdef REG_STARTEND |
#ifdef REG_STARTEND |
flags |= REG_STARTEND; |
flags |= REG_STARTEND; |
rm.rm_so = 0; |
rm.rm_so = 0; |
rm.rm_eo = line_len; |
rm.rm_eo = line_len; |
#endif |
#endif |
matched = !regexec(spattern, line, 1, &rm, flags); |
matched = !regexec(spattern, line, 1, &rm, flags); |
if (matched) |
if (matched) { |
{ |
|
#ifndef __WATCOMC__ |
|
*sp = line + rm.rm_so; |
*sp = line + rm.rm_so; |
*ep = line + rm.rm_eo; |
*ep = line + rm.rm_eo; |
#else |
|
*sp = rm.rm_sp; |
|
*ep = rm.rm_ep; |
|
#endif |
|
} |
} |
} |
} |
#endif |
|
#if HAVE_PCRE |
|
{ |
|
int flags = (notbol) ? PCRE_NOTBOL : 0; |
|
int ovector[3]; |
|
matched = pcre_exec(spattern, NULL, line, line_len, |
|
0, flags, ovector, 3) >= 0; |
|
if (matched) |
|
{ |
|
*sp = line + ovector[0]; |
|
*ep = line + ovector[1]; |
|
} |
|
} |
|
#endif |
|
#if HAVE_RE_COMP |
|
matched = (re_exec(line) == 1); |
|
/* |
|
* re_exec doesn't seem to provide a way to get the matched string. |
|
*/ |
|
*sp = *ep = NULL; |
|
#endif |
|
#if HAVE_REGCMP |
|
*ep = regex(spattern, line); |
|
matched = (*ep != NULL); |
|
if (matched) |
|
*sp = __loc1; |
|
#endif |
|
#if HAVE_V8_REGCOMP |
|
#if HAVE_REGEXEC2 |
|
matched = regexec2(spattern, line, notbol); |
|
#else |
|
matched = regexec(spattern, line); |
|
#endif |
|
if (matched) |
|
{ |
|
*sp = spattern->startp[0]; |
|
*ep = spattern->endp[0]; |
|
} |
|
#endif |
|
} |
|
matched = (!(search_type & SRCH_NO_MATCH) && matched) || |
matched = (!(search_type & SRCH_NO_MATCH) && matched) || |
((search_type & SRCH_NO_MATCH) && !matched); |
((search_type & SRCH_NO_MATCH) && !matched); |
return (matched); |
return (matched); |
} |
} |
|
|