2 * Copyright (C) 1984-2009 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
12 * Routines to do pattern matching.
21 * Compile a search pattern, for future use by match_pattern.
24 compile_pattern2(pattern
, search_type
, comp_pattern
)
29 if ((search_type
& SRCH_NO_REGEX
) == 0)
31 #if HAVE_POSIX_REGCOMP
32 regex_t
*comp
= (regex_t
*) ecalloc(1, sizeof(regex_t
));
33 regex_t
**pcomp
= (regex_t
**) comp_pattern
;
34 if (regcomp(comp
, pattern
, REGCOMP_FLAG
))
37 error("Invalid pattern", NULL_PARG
);
46 pcre
**pcomp
= (pcre
**) comp_pattern
;
47 const char *errstring
;
50 comp
= pcre_compile(pattern
, 0,
51 &errstring
, &erroffset
, NULL
);
54 parg
.p_string
= (char *) errstring
;
62 int *pcomp
= (int *) comp_pattern
;
63 if ((parg
.p_string
= re_comp(pattern
)) != NULL
)
72 char **pcomp
= (char **) comp_pattern
;
73 if ((comp
= regcmp(pattern
, 0)) == NULL
)
75 error("Invalid pattern", NULL_PARG
);
84 struct regexp
**pcomp
= (struct regexp
**) comp_pattern
;
85 if ((comp
= regcomp(pattern
)) == NULL
)
88 * regcomp has already printed an error message
102 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
105 compile_pattern(pattern
, search_type
, comp_pattern
)
113 if (caseless
!= OPT_ONPLUS
)
114 cvt_pattern
= pattern
;
117 cvt_pattern
= (char*) ecalloc(1, cvt_length(strlen(pattern
), CVT_TO_LC
));
118 cvt_text(cvt_pattern
, pattern
, (int *)NULL
, (int *)NULL
, CVT_TO_LC
);
120 result
= compile_pattern2(cvt_pattern
, search_type
, comp_pattern
);
121 if (cvt_pattern
!= pattern
)
127 * Forget that we have a compiled pattern.
130 uncompile_pattern(pattern
)
133 #if HAVE_POSIX_REGCOMP
134 regex_t
**pcomp
= (regex_t
**) pattern
;
140 pcre
**pcomp
= (pcre
**) pattern
;
146 int *pcomp
= (int *) pattern
;
150 char **pcomp
= (char **) pattern
;
156 struct regexp
**pcomp
= (struct regexp
**) pattern
;
164 * Is a compiled pattern null?
167 is_null_pattern(pattern
)
170 #if HAVE_POSIX_REGCOMP
171 return (pattern
== NULL
);
174 return (pattern
== NULL
);
177 return (pattern
== 0);
180 return (pattern
== NULL
);
183 return (pattern
== NULL
);
186 return (search_pattern
!= NULL
);
191 * Simple pattern matching function.
192 * It supports no metacharacters like *, etc.
195 match(pattern
, pattern_len
, buf
, buf_len
, pfound
, pend
)
200 char **pfound
, **pend
;
202 register char *pp
, *lp
;
203 register char *pattern_end
= pattern
+ pattern_len
;
204 register char *buf_end
= buf
+ buf_len
;
206 for ( ; buf
< buf_end
; buf
++)
208 for (pp
= pattern
, lp
= buf
; *pp
== *lp
; pp
++, lp
++)
209 if (pp
== pattern_end
|| lp
== buf_end
)
211 if (pp
== pattern_end
)
224 * Perform a pattern match with the previously compiled pattern.
225 * Set sp and ep to the start and end of the matched string.
228 match_pattern(pattern
, tpattern
, line
, line_len
, sp
, ep
, notbol
, search_type
)
239 #if HAVE_POSIX_REGCOMP
240 regex_t
*spattern
= (regex_t
*) pattern
;
243 pcre
*spattern
= (pcre
*) pattern
;
246 int spattern
= (int) pattern
;
249 char *spattern
= (char *) pattern
;
252 struct regexp
*spattern
= (struct regexp
*) pattern
;
255 if (search_type
& SRCH_NO_REGEX
)
256 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
, sp
, ep
);
259 #if HAVE_POSIX_REGCOMP
262 int flags
= (notbol
) ? REG_NOTBOL
: 0;
263 matched
= !regexec(spattern
, line
, 1, &rm
, flags
);
267 *sp
= line
+ rm
.rm_so
;
268 *ep
= line
+ rm
.rm_eo
;
278 int flags
= (notbol
) ? PCRE_NOTBOL
: 0;
280 matched
= pcre_exec(spattern
, NULL
, line
, line_len
,
281 0, flags
, ovector
, 3) >= 0;
284 *sp
= line
+ ovector
[0];
285 *ep
= line
+ ovector
[1];
290 matched
= (re_exec(line
) == 1);
292 * re_exec doesn't seem to provide a way to get the matched string.
297 *ep
= regex(spattern
, line
);
298 matched
= (*ep
!= NULL
);
304 matched
= regexec2(spattern
, line
, notbol
);
306 matched
= regexec(spattern
, line
);
310 *sp
= spattern
->startp
[0];
311 *ep
= spattern
->endp
[0];
315 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
, sp
, ep
);
318 matched
= (!(search_type
& SRCH_NO_MATCH
) && matched
) ||
319 ((search_type
& SRCH_NO_MATCH
) && !matched
);