Import less-436.
[dragonfly.git] / contrib / less / pattern.c
blobf1fb3ef697e38c85bab5869ef564923c3b23f6d9
1 /*
2 * Copyright (C) 1984-2009 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 about less, or for information on how to
8 * contact the author, see the README file.
9 */
12 * Routines to do pattern matching.
15 #include "less.h"
16 #include "pattern.h"
18 extern int caseless;
21 * Compile a search pattern, for future use by match_pattern.
23 static int
24 compile_pattern2(pattern, search_type, comp_pattern)
25 char *pattern;
26 int search_type;
27 void **comp_pattern;
29 if ((search_type & SRCH_NO_REGEX) == 0)
31 #if HAVE_POSIX_REGCOMP
32 regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
33 regex_t **pcomp = (regex_t **) comp_pattern;
34 if (regcomp(comp, pattern, REGCOMP_FLAG))
36 free(comp);
37 error("Invalid pattern", NULL_PARG);
38 return (-1);
40 if (*pcomp != NULL)
41 regfree(*pcomp);
42 *pcomp = comp;
43 #endif
44 #if HAVE_PCRE
45 pcre *comp;
46 pcre **pcomp = (pcre **) comp_pattern;
47 const char *errstring;
48 int erroffset;
49 PARG parg;
50 comp = pcre_compile(pattern, 0,
51 &errstring, &erroffset, NULL);
52 if (comp == NULL)
54 parg.p_string = (char *) errstring;
55 error("%s", &parg);
56 return (-1);
58 *pcomp = comp;
59 #endif
60 #if HAVE_RE_COMP
61 PARG parg;
62 int *pcomp = (int *) comp_pattern;
63 if ((parg.p_string = re_comp(pattern)) != NULL)
65 error("%s", &parg);
66 return (-1);
68 *pcomp = 1;
69 #endif
70 #if HAVE_REGCMP
71 char *comp;
72 char **pcomp = (char **) comp_pattern;
73 if ((comp = regcmp(pattern, 0)) == NULL)
75 error("Invalid pattern", NULL_PARG);
76 return (-1);
78 if (pcomp != NULL)
79 free(*pcomp);
80 *pcomp = comp;
81 #endif
82 #if HAVE_V8_REGCOMP
83 struct regexp *comp;
84 struct regexp **pcomp = (struct regexp **) comp_pattern;
85 if ((comp = regcomp(pattern)) == NULL)
88 * regcomp has already printed an error message
89 * via regerror().
91 return (-1);
93 if (*pcomp != NULL)
94 free(*pcomp);
95 *pcomp = comp;
96 #endif
98 return (0);
102 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
104 public int
105 compile_pattern(pattern, search_type, comp_pattern)
106 char *pattern;
107 int search_type;
108 void **comp_pattern;
110 char *cvt_pattern;
111 int result;
113 if (caseless != OPT_ONPLUS)
114 cvt_pattern = pattern;
115 else
117 cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
118 cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC);
120 result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
121 if (cvt_pattern != pattern)
122 free(cvt_pattern);
123 return (result);
127 * Forget that we have a compiled pattern.
129 public void
130 uncompile_pattern(pattern)
131 void **pattern;
133 #if HAVE_POSIX_REGCOMP
134 regex_t **pcomp = (regex_t **) pattern;
135 if (*pcomp != NULL)
136 regfree(*pcomp);
137 *pcomp = NULL;
138 #endif
139 #if HAVE_PCRE
140 pcre **pcomp = (pcre **) pattern;
141 if (*pcomp != NULL)
142 pcre_free(*pcomp);
143 *pcomp = NULL;
144 #endif
145 #if HAVE_RE_COMP
146 int *pcomp = (int *) pattern;
147 *pcomp = 0;
148 #endif
149 #if HAVE_REGCMP
150 char **pcomp = (char **) pattern;
151 if (*pcomp != NULL)
152 free(*pcomp);
153 *pcomp = NULL;
154 #endif
155 #if HAVE_V8_REGCOMP
156 struct regexp **pcomp = (struct regexp **) pattern;
157 if (*pcomp != NULL)
158 free(*pcomp);
159 *pcomp = NULL;
160 #endif
164 * Is a compiled pattern null?
166 public int
167 is_null_pattern(pattern)
168 void *pattern;
170 #if HAVE_POSIX_REGCOMP
171 return (pattern == NULL);
172 #endif
173 #if HAVE_PCRE
174 return (pattern == NULL);
175 #endif
176 #if HAVE_RE_COMP
177 return (pattern == 0);
178 #endif
179 #if HAVE_REGCMP
180 return (pattern == NULL);
181 #endif
182 #if HAVE_V8_REGCOMP
183 return (pattern == NULL);
184 #endif
185 #if NO_REGEX
186 return (search_pattern != NULL);
187 #endif
191 * Simple pattern matching function.
192 * It supports no metacharacters like *, etc.
194 static int
195 match(pattern, pattern_len, buf, buf_len, pfound, pend)
196 char *pattern;
197 int pattern_len;
198 char *buf;
199 int buf_len;
200 char **pfound, **pend;
202 register char *pp, *lp;
203 register char *pattern_end = pattern + pattern_len;
204 register char *buf_end = buf + buf_len;
206 for ( ; buf < buf_end; buf++)
208 for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
209 if (pp == pattern_end || lp == buf_end)
210 break;
211 if (pp == pattern_end)
213 if (pfound != NULL)
214 *pfound = buf;
215 if (pend != NULL)
216 *pend = lp;
217 return (1);
220 return (0);
224 * Perform a pattern match with the previously compiled pattern.
225 * Set sp and ep to the start and end of the matched string.
227 public int
228 match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
229 void *pattern;
230 char *tpattern;
231 char *line;
232 int line_len;
233 char **sp;
234 char **ep;
235 int notbol;
236 int search_type;
238 int matched;
239 #if HAVE_POSIX_REGCOMP
240 regex_t *spattern = (regex_t *) pattern;
241 #endif
242 #if HAVE_PCRE
243 pcre *spattern = (pcre *) pattern;
244 #endif
245 #if HAVE_RE_COMP
246 int spattern = (int) pattern;
247 #endif
248 #if HAVE_REGCMP
249 char *spattern = (char *) pattern;
250 #endif
251 #if HAVE_V8_REGCOMP
252 struct regexp *spattern = (struct regexp *) pattern;
253 #endif
255 if (search_type & SRCH_NO_REGEX)
256 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
257 else
259 #if HAVE_POSIX_REGCOMP
261 regmatch_t rm;
262 int flags = (notbol) ? REG_NOTBOL : 0;
263 matched = !regexec(spattern, line, 1, &rm, flags);
264 if (matched)
266 #ifndef __WATCOMC__
267 *sp = line + rm.rm_so;
268 *ep = line + rm.rm_eo;
269 #else
270 *sp = rm.rm_sp;
271 *ep = rm.rm_ep;
272 #endif
275 #endif
276 #if HAVE_PCRE
278 int flags = (notbol) ? PCRE_NOTBOL : 0;
279 int ovector[3];
280 matched = pcre_exec(spattern, NULL, line, line_len,
281 0, flags, ovector, 3) >= 0;
282 if (matched)
284 *sp = line + ovector[0];
285 *ep = line + ovector[1];
288 #endif
289 #if HAVE_RE_COMP
290 matched = (re_exec(line) == 1);
292 * re_exec doesn't seem to provide a way to get the matched string.
294 *sp = *ep = NULL;
295 #endif
296 #if HAVE_REGCMP
297 *ep = regex(spattern, line);
298 matched = (*ep != NULL);
299 if (matched)
300 *sp = __loc1;
301 #endif
302 #if HAVE_V8_REGCOMP
303 #if HAVE_REGEXEC2
304 matched = regexec2(spattern, line, notbol);
305 #else
306 matched = regexec(spattern, line);
307 #endif
308 if (matched)
310 *sp = spattern->startp[0];
311 *ep = spattern->endp[0];
313 #endif
314 #if NO_REGEX
315 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
316 #endif
318 matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
319 ((search_type & SRCH_NO_MATCH) && !matched);
320 return (matched);