2 * Copyright (C) 1984-2014 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, see the README file.
11 * Routines to do pattern matching.
20 * Compile a search pattern, for future use by match_pattern.
23 compile_pattern2(pattern
, search_type
, comp_pattern
, show_error
)
29 if (search_type
& SRCH_NO_REGEX
)
33 struct re_pattern_buffer
*comp
= (struct re_pattern_buffer
*)
34 ecalloc(1, sizeof(struct re_pattern_buffer
));
35 struct re_pattern_buffer
**pcomp
=
36 (struct re_pattern_buffer
**) comp_pattern
;
37 re_set_syntax(RE_SYNTAX_POSIX_EXTENDED
);
38 if (re_compile_pattern(pattern
, strlen(pattern
), comp
))
42 error("Invalid pattern", NULL_PARG
);
49 #if HAVE_POSIX_REGCOMP
50 regex_t
*comp
= (regex_t
*) ecalloc(1, sizeof(regex_t
));
51 regex_t
**pcomp
= (regex_t
**) comp_pattern
;
52 if (regcomp(comp
, pattern
, REGCOMP_FLAG
))
56 error("Invalid pattern", NULL_PARG
);
65 pcre
**pcomp
= (pcre
**) comp_pattern
;
66 constant
char *errstring
;
69 comp
= pcre_compile(pattern
, 0,
70 &errstring
, &erroffset
, NULL
);
73 parg
.p_string
= (char *) errstring
;
82 int *pcomp
= (int *) comp_pattern
;
83 if ((parg
.p_string
= re_comp(pattern
)) != NULL
)
93 char **pcomp
= (char **) comp_pattern
;
94 if ((comp
= regcmp(pattern
, 0)) == NULL
)
97 error("Invalid pattern", NULL_PARG
);
106 struct regexp
**pcomp
= (struct regexp
**) comp_pattern
;
107 reg_show_error
= show_error
;
108 comp
= regcomp(pattern
);
113 * regcomp has already printed an error message
127 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
130 compile_pattern(pattern
, search_type
, comp_pattern
)
138 if (caseless
!= OPT_ONPLUS
)
139 cvt_pattern
= pattern
;
142 cvt_pattern
= (char*) ecalloc(1, cvt_length(strlen(pattern
), CVT_TO_LC
));
143 cvt_text(cvt_pattern
, pattern
, (int *)NULL
, (int *)NULL
, CVT_TO_LC
);
145 result
= compile_pattern2(cvt_pattern
, search_type
, comp_pattern
, 1);
146 if (cvt_pattern
!= pattern
)
152 * Forget that we have a compiled pattern.
155 uncompile_pattern(pattern
)
159 struct re_pattern_buffer
**pcomp
= (struct re_pattern_buffer
**) pattern
;
164 #if HAVE_POSIX_REGCOMP
165 regex_t
**pcomp
= (regex_t
**) pattern
;
171 pcre
**pcomp
= (pcre
**) pattern
;
177 int *pcomp
= (int *) pattern
;
181 char **pcomp
= (char **) pattern
;
187 struct regexp
**pcomp
= (struct regexp
**) pattern
;
195 * Can a pattern be successfully compiled?
198 valid_pattern(pattern
)
204 CLEAR_PATTERN(comp_pattern
);
205 result
= compile_pattern2(pattern
, 0, &comp_pattern
, 0);
208 uncompile_pattern(&comp_pattern
);
213 * Is a compiled pattern null?
216 is_null_pattern(pattern
)
220 return (pattern
== NULL
);
222 #if HAVE_POSIX_REGCOMP
223 return (pattern
== NULL
);
226 return (pattern
== NULL
);
229 return (pattern
== 0);
232 return (pattern
== NULL
);
235 return (pattern
== NULL
);
240 * Simple pattern matching function.
241 * It supports no metacharacters like *, etc.
244 match(pattern
, pattern_len
, buf
, buf_len
, pfound
, pend
)
249 char **pfound
, **pend
;
251 register char *pp
, *lp
;
252 register char *pattern_end
= pattern
+ pattern_len
;
253 register char *buf_end
= buf
+ buf_len
;
255 for ( ; buf
< buf_end
; buf
++)
257 for (pp
= pattern
, lp
= buf
; *pp
== *lp
; pp
++, lp
++)
258 if (pp
== pattern_end
|| lp
== buf_end
)
260 if (pp
== pattern_end
)
273 * Perform a pattern match with the previously compiled pattern.
274 * Set sp and ep to the start and end of the matched string.
277 match_pattern(pattern
, tpattern
, line
, line_len
, sp
, ep
, notbol
, search_type
)
289 struct re_pattern_buffer
*spattern
= (struct re_pattern_buffer
*) pattern
;
291 #if HAVE_POSIX_REGCOMP
292 regex_t
*spattern
= (regex_t
*) pattern
;
295 pcre
*spattern
= (pcre
*) pattern
;
298 int spattern
= (int) pattern
;
301 char *spattern
= (char *) pattern
;
304 struct regexp
*spattern
= (struct regexp
*) pattern
;
308 search_type
|= SRCH_NO_REGEX
;
310 if (search_type
& SRCH_NO_REGEX
)
311 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
, sp
, ep
);
316 struct re_registers search_regs
;
317 spattern
->not_bol
= notbol
;
318 spattern
->regs_allocated
= REGS_UNALLOCATED
;
319 matched
= re_search(spattern
, line
, line_len
, 0, line_len
, &search_regs
) >= 0;
322 *sp
= line
+ search_regs
.start
[0];
323 *ep
= line
+ search_regs
.end
[0];
327 #if HAVE_POSIX_REGCOMP
330 int flags
= (notbol
) ? REG_NOTBOL
: 0;
332 flags
|= REG_STARTEND
;
336 matched
= !regexec(spattern
, line
, 1, &rm
, flags
);
340 *sp
= line
+ rm
.rm_so
;
341 *ep
= line
+ rm
.rm_eo
;
351 int flags
= (notbol
) ? PCRE_NOTBOL
: 0;
353 matched
= pcre_exec(spattern
, NULL
, line
, line_len
,
354 0, flags
, ovector
, 3) >= 0;
357 *sp
= line
+ ovector
[0];
358 *ep
= line
+ ovector
[1];
363 matched
= (re_exec(line
) == 1);
365 * re_exec doesn't seem to provide a way to get the matched string.
370 *ep
= regex(spattern
, line
);
371 matched
= (*ep
!= NULL
);
377 matched
= regexec2(spattern
, line
, notbol
);
379 matched
= regexec(spattern
, line
);
383 *sp
= spattern
->startp
[0];
384 *ep
= spattern
->endp
[0];
388 matched
= (!(search_type
& SRCH_NO_MATCH
) && matched
) ||
389 ((search_type
& SRCH_NO_MATCH
) && !matched
);