1 /* $NetBSD: pattern.c,v 1.3 2013/09/04 19:44:21 tron Exp $ */
4 * Copyright (C) 1984-2012 Mark Nudelman
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Less License, as specified in the README file.
9 * For more information, see the README file.
13 * Routines to do pattern matching.
22 * Compile a search pattern, for future use by match_pattern.
25 compile_pattern2(pattern
, search_type
, comp_pattern
)
30 if (search_type
& SRCH_NO_REGEX
)
34 struct re_pattern_buffer
*comp
= (struct re_pattern_buffer
*)
35 ecalloc(1, sizeof(struct re_pattern_buffer
));
36 struct re_pattern_buffer
**pcomp
=
37 (struct re_pattern_buffer
**) comp_pattern
;
38 re_set_syntax(RE_SYNTAX_POSIX_EXTENDED
);
39 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
))
55 error("Invalid pattern", NULL_PARG
);
64 pcre
**pcomp
= (pcre
**) comp_pattern
;
65 constant
char *errstring
;
68 comp
= pcre_compile(pattern
, 0,
69 &errstring
, &erroffset
, NULL
);
72 parg
.p_string
= (char *) errstring
;
80 int *pcomp
= (int *) comp_pattern
;
81 if ((parg
.p_string
= re_comp(pattern
)) != NULL
)
90 char **pcomp
= (char **) comp_pattern
;
91 if ((comp
= regcmp(pattern
, 0)) == NULL
)
93 error("Invalid pattern", NULL_PARG
);
102 struct regexp
**pcomp
= (struct regexp
**) comp_pattern
;
103 if ((comp
= regcomp(pattern
)) == NULL
)
106 * regcomp has already printed an error message
120 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
123 compile_pattern(pattern
, search_type
, comp_pattern
)
131 if (caseless
!= OPT_ONPLUS
)
132 cvt_pattern
= pattern
;
135 cvt_pattern
= (char*) ecalloc(1, cvt_length(strlen(pattern
), CVT_TO_LC
));
136 cvt_text(cvt_pattern
, pattern
, (int *)NULL
, (int *)NULL
, CVT_TO_LC
);
138 result
= compile_pattern2(cvt_pattern
, search_type
, comp_pattern
);
139 if (cvt_pattern
!= pattern
)
145 * Forget that we have a compiled pattern.
148 uncompile_pattern(pattern
)
152 struct re_pattern_buffer
**pcomp
= (struct re_pattern_buffer
**) pattern
;
157 #if HAVE_POSIX_REGCOMP
158 regex_t
**pcomp
= (regex_t
**) pattern
;
164 pcre
**pcomp
= (pcre
**) pattern
;
170 int *pcomp
= (int *) pattern
;
174 char **pcomp
= (char **) pattern
;
180 struct regexp
**pcomp
= (struct regexp
**) pattern
;
188 * Is a compiled pattern null?
191 is_null_pattern(pattern
)
195 return (pattern
== NULL
);
197 #if HAVE_POSIX_REGCOMP
198 return (pattern
== NULL
);
201 return (pattern
== NULL
);
204 return (pattern
== 0);
207 return (pattern
== NULL
);
210 return (pattern
== NULL
);
215 * Simple pattern matching function.
216 * It supports no metacharacters like *, etc.
219 match(pattern
, pattern_len
, buf
, buf_len
, pfound
, pend
)
224 char **pfound
, **pend
;
226 register char *pp
, *lp
;
227 register char *pattern_end
= pattern
+ pattern_len
;
228 register char *buf_end
= buf
+ buf_len
;
230 for ( ; buf
< buf_end
; buf
++)
232 for (pp
= pattern
, lp
= buf
; *pp
== *lp
; pp
++, lp
++)
233 if (pp
== pattern_end
|| lp
== buf_end
)
235 if (pp
== pattern_end
)
248 * Perform a pattern match with the previously compiled pattern.
249 * Set sp and ep to the start and end of the matched string.
252 match_pattern(pattern
, tpattern
, line
, line_len
, sp
, ep
, notbol
, search_type
)
264 struct re_pattern_buffer
*spattern
= (struct re_pattern_buffer
*) pattern
;
266 #if HAVE_POSIX_REGCOMP
267 regex_t
*spattern
= (regex_t
*) pattern
;
270 pcre
*spattern
= (pcre
*) pattern
;
273 int spattern
= (int) pattern
;
276 char *spattern
= (char *) pattern
;
279 struct regexp
*spattern
= (struct regexp
*) pattern
;
283 search_type
|= SRCH_NO_REGEX
;
285 if (search_type
& SRCH_NO_REGEX
)
286 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
, sp
, ep
);
291 struct re_registers search_regs
;
292 regoff_t
*starts
= (regoff_t
*) ecalloc(1, sizeof (regoff_t
));
293 regoff_t
*ends
= (regoff_t
*) ecalloc(1, sizeof (regoff_t
));
294 spattern
->not_bol
= notbol
;
295 re_set_registers(spattern
, &search_regs
, 1, starts
, ends
);
296 matched
= re_search(spattern
, line
, line_len
, 0, line_len
, &search_regs
) >= 0;
299 *sp
= line
+ search_regs
.start
[0];
300 *ep
= line
+ search_regs
.end
[0];
306 #if HAVE_POSIX_REGCOMP
309 int flags
= (notbol
) ? REG_NOTBOL
: 0;
310 matched
= !regexec(spattern
, line
, 1, &rm
, flags
);
314 *sp
= line
+ rm
.rm_so
;
315 *ep
= line
+ rm
.rm_eo
;
325 int flags
= (notbol
) ? PCRE_NOTBOL
: 0;
327 matched
= pcre_exec(spattern
, NULL
, line
, line_len
,
328 0, flags
, ovector
, 3) >= 0;
331 *sp
= line
+ ovector
[0];
332 *ep
= line
+ ovector
[1];
337 matched
= (re_exec(line
) == 1);
339 * re_exec doesn't seem to provide a way to get the matched string.
344 *ep
= regex(spattern
, line
);
345 matched
= (*ep
!= NULL
);
351 matched
= regexec2(spattern
, line
, notbol
);
353 matched
= regexec(spattern
, line
);
357 *sp
= spattern
->startp
[0];
358 *ep
= spattern
->endp
[0];
362 matched
= (!(search_type
& SRCH_NO_MATCH
) && matched
) ||
363 ((search_type
& SRCH_NO_MATCH
) && !matched
);