gcc80: Add missing atomic variants in libgcov.
[dragonfly.git] / contrib / less / pattern.c
blob71141c7d05fe2c690df127f6c010e4ef57cef969
1 /*
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.
8 */
11 * Routines to do pattern matching.
14 #include "less.h"
15 #include "pattern.h"
17 extern int caseless;
20 * Compile a search pattern, for future use by match_pattern.
22 static int
23 compile_pattern2(pattern, search_type, comp_pattern, show_error)
24 char *pattern;
25 int search_type;
26 void **comp_pattern;
27 int show_error;
29 if (search_type & SRCH_NO_REGEX)
30 return (0);
32 #if HAVE_GNU_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))
40 free(comp);
41 if (show_error)
42 error("Invalid pattern", NULL_PARG);
43 return (-1);
45 if (*pcomp != NULL)
46 regfree(*pcomp);
47 *pcomp = comp;
48 #endif
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))
54 free(comp);
55 if (show_error)
56 error("Invalid pattern", NULL_PARG);
57 return (-1);
59 if (*pcomp != NULL)
60 regfree(*pcomp);
61 *pcomp = comp;
62 #endif
63 #if HAVE_PCRE
64 pcre *comp;
65 pcre **pcomp = (pcre **) comp_pattern;
66 constant char *errstring;
67 int erroffset;
68 PARG parg;
69 comp = pcre_compile(pattern, 0,
70 &errstring, &erroffset, NULL);
71 if (comp == NULL)
73 parg.p_string = (char *) errstring;
74 if (show_error)
75 error("%s", &parg);
76 return (-1);
78 *pcomp = comp;
79 #endif
80 #if HAVE_RE_COMP
81 PARG parg;
82 int *pcomp = (int *) comp_pattern;
83 if ((parg.p_string = re_comp(pattern)) != NULL)
85 if (show_error)
86 error("%s", &parg);
87 return (-1);
89 *pcomp = 1;
90 #endif
91 #if HAVE_REGCMP
92 char *comp;
93 char **pcomp = (char **) comp_pattern;
94 if ((comp = regcmp(pattern, 0)) == NULL)
96 if (show_error)
97 error("Invalid pattern", NULL_PARG);
98 return (-1);
100 if (pcomp != NULL)
101 free(*pcomp);
102 *pcomp = comp;
103 #endif
104 #if HAVE_V8_REGCOMP
105 struct regexp *comp;
106 struct regexp **pcomp = (struct regexp **) comp_pattern;
107 reg_show_error = show_error;
108 comp = regcomp(pattern);
109 reg_show_error = 1;
110 if (comp == NULL)
113 * regcomp has already printed an error message
114 * via regerror().
116 return (-1);
118 if (*pcomp != NULL)
119 free(*pcomp);
120 *pcomp = comp;
121 #endif
123 return (0);
127 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
129 public int
130 compile_pattern(pattern, search_type, comp_pattern)
131 char *pattern;
132 int search_type;
133 void **comp_pattern;
135 char *cvt_pattern;
136 int result;
138 if (caseless != OPT_ONPLUS)
139 cvt_pattern = pattern;
140 else
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)
147 free(cvt_pattern);
148 return (result);
152 * Forget that we have a compiled pattern.
154 public void
155 uncompile_pattern(pattern)
156 void **pattern;
158 #if HAVE_GNU_REGEX
159 struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern;
160 if (*pcomp != NULL)
161 regfree(*pcomp);
162 *pcomp = NULL;
163 #endif
164 #if HAVE_POSIX_REGCOMP
165 regex_t **pcomp = (regex_t **) pattern;
166 if (*pcomp != NULL)
167 regfree(*pcomp);
168 *pcomp = NULL;
169 #endif
170 #if HAVE_PCRE
171 pcre **pcomp = (pcre **) pattern;
172 if (*pcomp != NULL)
173 pcre_free(*pcomp);
174 *pcomp = NULL;
175 #endif
176 #if HAVE_RE_COMP
177 int *pcomp = (int *) pattern;
178 *pcomp = 0;
179 #endif
180 #if HAVE_REGCMP
181 char **pcomp = (char **) pattern;
182 if (*pcomp != NULL)
183 free(*pcomp);
184 *pcomp = NULL;
185 #endif
186 #if HAVE_V8_REGCOMP
187 struct regexp **pcomp = (struct regexp **) pattern;
188 if (*pcomp != NULL)
189 free(*pcomp);
190 *pcomp = NULL;
191 #endif
195 * Can a pattern be successfully compiled?
197 public int
198 valid_pattern(pattern)
199 char *pattern;
201 void *comp_pattern;
202 int result;
204 CLEAR_PATTERN(comp_pattern);
205 result = compile_pattern2(pattern, 0, &comp_pattern, 0);
206 if (result != 0)
207 return (0);
208 uncompile_pattern(&comp_pattern);
209 return (1);
213 * Is a compiled pattern null?
215 public int
216 is_null_pattern(pattern)
217 void *pattern;
219 #if HAVE_GNU_REGEX
220 return (pattern == NULL);
221 #endif
222 #if HAVE_POSIX_REGCOMP
223 return (pattern == NULL);
224 #endif
225 #if HAVE_PCRE
226 return (pattern == NULL);
227 #endif
228 #if HAVE_RE_COMP
229 return (pattern == 0);
230 #endif
231 #if HAVE_REGCMP
232 return (pattern == NULL);
233 #endif
234 #if HAVE_V8_REGCOMP
235 return (pattern == NULL);
236 #endif
237 #if NO_REGEX
238 return (pattern == NULL);
239 #endif
243 * Simple pattern matching function.
244 * It supports no metacharacters like *, etc.
246 static int
247 match(pattern, pattern_len, buf, buf_len, pfound, pend)
248 char *pattern;
249 int pattern_len;
250 char *buf;
251 int buf_len;
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++)
262 char cp = *pp;
263 char cl = *lp;
264 if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
265 cp = ASCII_TO_LOWER(cp);
266 if (cp != cl)
267 break;
268 if (pp == pattern_end || lp == buf_end)
269 break;
271 if (pp == pattern_end)
273 if (pfound != NULL)
274 *pfound = buf;
275 if (pend != NULL)
276 *pend = lp;
277 return (1);
280 return (0);
284 * Perform a pattern match with the previously compiled pattern.
285 * Set sp and ep to the start and end of the matched string.
287 public int
288 match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
289 void *pattern;
290 char *tpattern;
291 char *line;
292 int line_len;
293 char **sp;
294 char **ep;
295 int notbol;
296 int search_type;
298 int matched;
299 #if HAVE_GNU_REGEX
300 struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern;
301 #endif
302 #if HAVE_POSIX_REGCOMP
303 regex_t *spattern = (regex_t *) pattern;
304 #endif
305 #if HAVE_PCRE
306 pcre *spattern = (pcre *) pattern;
307 #endif
308 #if HAVE_RE_COMP
309 int spattern = (int) pattern;
310 #endif
311 #if HAVE_REGCMP
312 char *spattern = (char *) pattern;
313 #endif
314 #if HAVE_V8_REGCOMP
315 struct regexp *spattern = (struct regexp *) pattern;
316 #endif
318 *sp = *ep = NULL;
319 #if NO_REGEX
320 search_type |= SRCH_NO_REGEX;
321 #endif
322 if (search_type & SRCH_NO_REGEX)
323 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
324 else
326 #if HAVE_GNU_REGEX
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;
332 if (matched)
334 *sp = line + search_regs.start[0];
335 *ep = line + search_regs.end[0];
338 #endif
339 #if HAVE_POSIX_REGCOMP
341 regmatch_t rm;
342 int flags = (notbol) ? REG_NOTBOL : 0;
343 #ifdef REG_STARTEND
344 flags |= REG_STARTEND;
345 rm.rm_so = 0;
346 rm.rm_eo = line_len;
347 #endif
348 matched = !regexec(spattern, line, 1, &rm, flags);
349 if (matched)
351 #ifndef __WATCOMC__
352 *sp = line + rm.rm_so;
353 *ep = line + rm.rm_eo;
354 #else
355 *sp = rm.rm_sp;
356 *ep = rm.rm_ep;
357 #endif
360 #endif
361 #if HAVE_PCRE
363 int flags = (notbol) ? PCRE_NOTBOL : 0;
364 int ovector[3];
365 matched = pcre_exec(spattern, NULL, line, line_len,
366 0, flags, ovector, 3) >= 0;
367 if (matched)
369 *sp = line + ovector[0];
370 *ep = line + ovector[1];
373 #endif
374 #if HAVE_RE_COMP
375 matched = (re_exec(line) == 1);
377 * re_exec doesn't seem to provide a way to get the matched string.
379 *sp = *ep = NULL;
380 #endif
381 #if HAVE_REGCMP
382 *ep = regex(spattern, line);
383 matched = (*ep != NULL);
384 if (matched)
385 *sp = __loc1;
386 #endif
387 #if HAVE_V8_REGCOMP
388 #if HAVE_REGEXEC2
389 matched = regexec2(spattern, line, notbol);
390 #else
391 matched = regexec(spattern, line);
392 #endif
393 if (matched)
395 *sp = spattern->startp[0];
396 *ep = spattern->endp[0];
398 #endif
400 matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
401 ((search_type & SRCH_NO_MATCH) && !matched);
402 return (matched);