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);