etc/services - sync with NetBSD-8
[minix.git] / external / bsd / less / dist / pattern.c
blobdb82076c02fbc204e1a0877c4eb8a4d10c829aee
1 /* $NetBSD: pattern.c,v 1.3 2013/09/04 19:44:21 tron Exp $ */
3 /*
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.
16 #include "less.h"
17 #include "pattern.h"
19 extern int caseless;
22 * Compile a search pattern, for future use by match_pattern.
24 static int
25 compile_pattern2(pattern, search_type, comp_pattern)
26 char *pattern;
27 int search_type;
28 void **comp_pattern;
30 if (search_type & SRCH_NO_REGEX)
31 return (0);
33 #if HAVE_GNU_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))
41 free(comp);
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 error("Invalid pattern", NULL_PARG);
56 return (-1);
58 if (*pcomp != NULL)
59 regfree(*pcomp);
60 *pcomp = comp;
61 #endif
62 #if HAVE_PCRE
63 pcre *comp;
64 pcre **pcomp = (pcre **) comp_pattern;
65 constant char *errstring;
66 int erroffset;
67 PARG parg;
68 comp = pcre_compile(pattern, 0,
69 &errstring, &erroffset, NULL);
70 if (comp == NULL)
72 parg.p_string = (char *) errstring;
73 error("%s", &parg);
74 return (-1);
76 *pcomp = comp;
77 #endif
78 #if HAVE_RE_COMP
79 PARG parg;
80 int *pcomp = (int *) comp_pattern;
81 if ((parg.p_string = re_comp(pattern)) != NULL)
83 error("%s", &parg);
84 return (-1);
86 *pcomp = 1;
87 #endif
88 #if HAVE_REGCMP
89 char *comp;
90 char **pcomp = (char **) comp_pattern;
91 if ((comp = regcmp(pattern, 0)) == NULL)
93 error("Invalid pattern", NULL_PARG);
94 return (-1);
96 if (pcomp != NULL)
97 free(*pcomp);
98 *pcomp = comp;
99 #endif
100 #if HAVE_V8_REGCOMP
101 struct regexp *comp;
102 struct regexp **pcomp = (struct regexp **) comp_pattern;
103 if ((comp = regcomp(pattern)) == NULL)
106 * regcomp has already printed an error message
107 * via regerror().
109 return (-1);
111 if (*pcomp != NULL)
112 free(*pcomp);
113 *pcomp = comp;
114 #endif
116 return (0);
120 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
122 public int
123 compile_pattern(pattern, search_type, comp_pattern)
124 char *pattern;
125 int search_type;
126 void **comp_pattern;
128 char *cvt_pattern;
129 int result;
131 if (caseless != OPT_ONPLUS)
132 cvt_pattern = pattern;
133 else
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)
140 free(cvt_pattern);
141 return (result);
145 * Forget that we have a compiled pattern.
147 public void
148 uncompile_pattern(pattern)
149 void **pattern;
151 #if HAVE_GNU_REGEX
152 struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern;
153 if (*pcomp != NULL)
154 regfree(*pcomp);
155 *pcomp = NULL;
156 #endif
157 #if HAVE_POSIX_REGCOMP
158 regex_t **pcomp = (regex_t **) pattern;
159 if (*pcomp != NULL)
160 regfree(*pcomp);
161 *pcomp = NULL;
162 #endif
163 #if HAVE_PCRE
164 pcre **pcomp = (pcre **) pattern;
165 if (*pcomp != NULL)
166 pcre_free(*pcomp);
167 *pcomp = NULL;
168 #endif
169 #if HAVE_RE_COMP
170 int *pcomp = (int *) pattern;
171 *pcomp = 0;
172 #endif
173 #if HAVE_REGCMP
174 char **pcomp = (char **) pattern;
175 if (*pcomp != NULL)
176 free(*pcomp);
177 *pcomp = NULL;
178 #endif
179 #if HAVE_V8_REGCOMP
180 struct regexp **pcomp = (struct regexp **) pattern;
181 if (*pcomp != NULL)
182 free(*pcomp);
183 *pcomp = NULL;
184 #endif
188 * Is a compiled pattern null?
190 public int
191 is_null_pattern(pattern)
192 void *pattern;
194 #if HAVE_GNU_REGEX
195 return (pattern == NULL);
196 #endif
197 #if HAVE_POSIX_REGCOMP
198 return (pattern == NULL);
199 #endif
200 #if HAVE_PCRE
201 return (pattern == NULL);
202 #endif
203 #if HAVE_RE_COMP
204 return (pattern == 0);
205 #endif
206 #if HAVE_REGCMP
207 return (pattern == NULL);
208 #endif
209 #if HAVE_V8_REGCOMP
210 return (pattern == NULL);
211 #endif
215 * Simple pattern matching function.
216 * It supports no metacharacters like *, etc.
218 static int
219 match(pattern, pattern_len, buf, buf_len, pfound, pend)
220 char *pattern;
221 int pattern_len;
222 char *buf;
223 int buf_len;
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)
234 break;
235 if (pp == pattern_end)
237 if (pfound != NULL)
238 *pfound = buf;
239 if (pend != NULL)
240 *pend = lp;
241 return (1);
244 return (0);
248 * Perform a pattern match with the previously compiled pattern.
249 * Set sp and ep to the start and end of the matched string.
251 public int
252 match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
253 void *pattern;
254 char *tpattern;
255 char *line;
256 int line_len;
257 char **sp;
258 char **ep;
259 int notbol;
260 int search_type;
262 int matched;
263 #if HAVE_GNU_REGEX
264 struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern;
265 #endif
266 #if HAVE_POSIX_REGCOMP
267 regex_t *spattern = (regex_t *) pattern;
268 #endif
269 #if HAVE_PCRE
270 pcre *spattern = (pcre *) pattern;
271 #endif
272 #if HAVE_RE_COMP
273 int spattern = (int) pattern;
274 #endif
275 #if HAVE_REGCMP
276 char *spattern = (char *) pattern;
277 #endif
278 #if HAVE_V8_REGCOMP
279 struct regexp *spattern = (struct regexp *) pattern;
280 #endif
282 #if NO_REGEX
283 search_type |= SRCH_NO_REGEX;
284 #endif
285 if (search_type & SRCH_NO_REGEX)
286 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
287 else
289 #if HAVE_GNU_REGEX
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;
297 if (matched)
299 *sp = line + search_regs.start[0];
300 *ep = line + search_regs.end[0];
302 free(starts);
303 free(ends);
305 #endif
306 #if HAVE_POSIX_REGCOMP
308 regmatch_t rm;
309 int flags = (notbol) ? REG_NOTBOL : 0;
310 matched = !regexec(spattern, line, 1, &rm, flags);
311 if (matched)
313 #ifndef __WATCOMC__
314 *sp = line + rm.rm_so;
315 *ep = line + rm.rm_eo;
316 #else
317 *sp = rm.rm_sp;
318 *ep = rm.rm_ep;
319 #endif
322 #endif
323 #if HAVE_PCRE
325 int flags = (notbol) ? PCRE_NOTBOL : 0;
326 int ovector[3];
327 matched = pcre_exec(spattern, NULL, line, line_len,
328 0, flags, ovector, 3) >= 0;
329 if (matched)
331 *sp = line + ovector[0];
332 *ep = line + ovector[1];
335 #endif
336 #if HAVE_RE_COMP
337 matched = (re_exec(line) == 1);
339 * re_exec doesn't seem to provide a way to get the matched string.
341 *sp = *ep = NULL;
342 #endif
343 #if HAVE_REGCMP
344 *ep = regex(spattern, line);
345 matched = (*ep != NULL);
346 if (matched)
347 *sp = __loc1;
348 #endif
349 #if HAVE_V8_REGCOMP
350 #if HAVE_REGEXEC2
351 matched = regexec2(spattern, line, notbol);
352 #else
353 matched = regexec(spattern, line);
354 #endif
355 if (matched)
357 *sp = spattern->startp[0];
358 *ep = spattern->endp[0];
360 #endif
362 matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
363 ((search_type & SRCH_NO_MATCH) && !matched);
364 return (matched);