2 * Copyright (C) 1984-2015 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
);
238 return (pattern
== NULL
);
243 * Simple pattern matching function.
244 * It supports no metacharacters like *, etc.
247 match(pattern
, pattern_len
, buf
, buf_len
, pfound
, pend
)
252 char **pfound
, **pend
;
254 register char *pp
, *lp
;
255 register char *pattern_end
= pattern
+ pattern_len
;
256 register char *buf_end
= buf
+ buf_len
;
258 for ( ; buf
< buf_end
; buf
++)
260 for (pp
= pattern
, lp
= buf
; ; pp
++, lp
++)
264 if (caseless
== OPT_ONPLUS
&& ASCII_IS_UPPER(cp
))
265 cp
= ASCII_TO_LOWER(cp
);
268 if (pp
== pattern_end
|| lp
== buf_end
)
271 if (pp
== pattern_end
)
284 * Perform a pattern match with the previously compiled pattern.
285 * Set sp and ep to the start and end of the matched string.
288 match_pattern(pattern
, tpattern
, line
, line_len
, sp
, ep
, notbol
, search_type
)
300 struct re_pattern_buffer
*spattern
= (struct re_pattern_buffer
*) pattern
;
302 #if HAVE_POSIX_REGCOMP
303 regex_t
*spattern
= (regex_t
*) pattern
;
306 pcre
*spattern
= (pcre
*) pattern
;
309 int spattern
= (int) pattern
;
312 char *spattern
= (char *) pattern
;
315 struct regexp
*spattern
= (struct regexp
*) pattern
;
320 search_type
|= SRCH_NO_REGEX
;
322 if (search_type
& SRCH_NO_REGEX
)
323 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
, sp
, ep
);
328 struct re_registers search_regs
;
329 spattern
->not_bol
= notbol
;
330 spattern
->regs_allocated
= REGS_UNALLOCATED
;
331 matched
= re_search(spattern
, line
, line_len
, 0, line_len
, &search_regs
) >= 0;
334 *sp
= line
+ search_regs
.start
[0];
335 *ep
= line
+ search_regs
.end
[0];
339 #if HAVE_POSIX_REGCOMP
342 int flags
= (notbol
) ? REG_NOTBOL
: 0;
344 flags
|= REG_STARTEND
;
348 matched
= !regexec(spattern
, line
, 1, &rm
, flags
);
352 *sp
= line
+ rm
.rm_so
;
353 *ep
= line
+ rm
.rm_eo
;
363 int flags
= (notbol
) ? PCRE_NOTBOL
: 0;
365 matched
= pcre_exec(spattern
, NULL
, line
, line_len
,
366 0, flags
, ovector
, 3) >= 0;
369 *sp
= line
+ ovector
[0];
370 *ep
= line
+ ovector
[1];
375 matched
= (re_exec(line
) == 1);
377 * re_exec doesn't seem to provide a way to get the matched string.
382 *ep
= regex(spattern
, line
);
383 matched
= (*ep
!= NULL
);
389 matched
= regexec2(spattern
, line
, notbol
);
391 matched
= regexec(spattern
, line
);
395 *sp
= spattern
->startp
[0];
396 *ep
= spattern
->endp
[0];
400 matched
= (!(search_type
& SRCH_NO_MATCH
) && matched
) ||
401 ((search_type
& SRCH_NO_MATCH
) && !matched
);