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(char *pattern, int search_type, void **comp_pattern, int show_error)
25 if (search_type & SRCH_NO_REGEX)
29 struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
30 ecalloc(1, sizeof(struct re_pattern_buffer));
31 struct re_pattern_buffer **pcomp =
32 (struct re_pattern_buffer **) comp_pattern;
33 re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
34 if (re_compile_pattern(pattern, strlen(pattern), comp))
38 error("Invalid pattern", NULL_PARG);
45 #if HAVE_POSIX_REGCOMP
46 regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
47 regex_t **pcomp = (regex_t **) comp_pattern;
48 if (regcomp(comp, pattern, REGCOMP_FLAG))
52 error("Invalid pattern", NULL_PARG);
61 pcre **pcomp = (pcre **) comp_pattern;
62 constant char *errstring;
65 comp = pcre_compile(pattern, 0,
66 &errstring, &erroffset, NULL);
69 parg.p_string = (char *) errstring;
78 int *pcomp = (int *) comp_pattern;
79 if ((parg.p_string = re_comp(pattern)) != NULL)
89 char **pcomp = (char **) comp_pattern;
90 if ((comp = regcmp(pattern, 0)) == NULL)
93 error("Invalid pattern", NULL_PARG);
102 struct regexp **pcomp = (struct regexp **) comp_pattern;
103 reg_show_error = show_error;
104 comp = regcomp(pattern);
109 * regcomp has already printed an error message
123 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
126 compile_pattern(char *pattern, int search_type, void **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, 1);
139 if (cvt_pattern != pattern)
145 * Forget that we have a compiled pattern.
148 uncompile_pattern(void **pattern)
151 struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern;
156 #if HAVE_POSIX_REGCOMP
157 regex_t **pcomp = (regex_t **) pattern;
163 pcre **pcomp = (pcre **) pattern;
169 int *pcomp = (int *) pattern;
173 char **pcomp = (char **) pattern;
179 struct regexp **pcomp = (struct regexp **) pattern;
187 * Can a pattern be successfully compiled?
190 valid_pattern(char *pattern)
195 CLEAR_PATTERN(comp_pattern);
196 result = compile_pattern2(pattern, 0, &comp_pattern, 0);
199 uncompile_pattern(&comp_pattern);
204 * Is a compiled pattern null?
207 is_null_pattern(void *pattern)
210 return (pattern == NULL);
212 #if HAVE_POSIX_REGCOMP
213 return (pattern == NULL);
216 return (pattern == NULL);
219 return (pattern == 0);
222 return (pattern == NULL);
225 return (pattern == NULL);
228 return (pattern == NULL);
233 * Simple pattern matching function.
234 * It supports no metacharacters like *, etc.
237 match(char *pattern, int pattern_len, char *buf, int buf_len, char **pfound, char **pend)
240 char *pattern_end = pattern + pattern_len;
241 char *buf_end = buf + buf_len;
243 for ( ; buf < buf_end; buf++)
245 for (pp = pattern, lp = buf; ; pp++, lp++)
249 if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
250 cp = ASCII_TO_LOWER(cp);
253 if (pp == pattern_end || lp == buf_end)
256 if (pp == pattern_end)
269 * Perform a pattern match with the previously compiled pattern.
270 * Set sp and ep to the start and end of the matched string.
273 match_pattern(void *pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int notbol, int search_type)
277 struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern;
279 #if HAVE_POSIX_REGCOMP
280 regex_t *spattern = (regex_t *) pattern;
283 pcre *spattern = (pcre *) pattern;
286 int spattern = (int) pattern;
289 char *spattern = (char *) pattern;
292 struct regexp *spattern = (struct regexp *) pattern;
297 search_type |= SRCH_NO_REGEX;
299 if (search_type & SRCH_NO_REGEX)
300 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
305 struct re_registers search_regs;
306 spattern->not_bol = notbol;
307 spattern->regs_allocated = REGS_UNALLOCATED;
308 matched = re_search(spattern, line, line_len, 0, line_len, &search_regs) >= 0;
311 *sp = line + search_regs.start[0];
312 *ep = line + search_regs.end[0];
316 #if HAVE_POSIX_REGCOMP
319 int flags = (notbol) ? REG_NOTBOL : 0;
321 flags |= REG_STARTEND;
325 matched = !regexec(spattern, line, 1, &rm, flags);
329 *sp = line + rm.rm_so;
330 *ep = line + rm.rm_eo;
340 int flags = (notbol) ? PCRE_NOTBOL : 0;
342 matched = pcre_exec(spattern, NULL, line, line_len,
343 0, flags, ovector, 3) >= 0;
346 *sp = line + ovector[0];
347 *ep = line + ovector[1];
352 matched = (re_exec(line) == 1);
354 * re_exec doesn't seem to provide a way to get the matched string.
359 *ep = regex(spattern, line);
360 matched = (*ep != NULL);
366 matched = regexec2(spattern, line, notbol);
368 matched = regexec(spattern, line);
372 *sp = spattern->startp[0];
373 *ep = spattern->endp[0];
377 matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
378 ((search_type & SRCH_NO_MATCH) && !matched);