xref: /freebsd/contrib/less/pattern.c (revision c77c488926555ca344ae3a417544cf7a720e1de1)
1f0be0a1fSXin LI /*
2*c77c4889SXin LI  * Copyright (C) 1984-2024  Mark Nudelman
3f0be0a1fSXin LI  *
4f0be0a1fSXin LI  * You may distribute under the terms of either the GNU General Public
5f0be0a1fSXin LI  * License or the Less License, as specified in the README file.
6f0be0a1fSXin LI  *
796e55cc7SXin LI  * For more information, see the README file.
8f0be0a1fSXin LI  */
9f0be0a1fSXin LI 
10f0be0a1fSXin LI /*
11f0be0a1fSXin LI  * Routines to do pattern matching.
12f0be0a1fSXin LI  */
13f0be0a1fSXin LI 
14f0be0a1fSXin LI #include "less.h"
15f0be0a1fSXin LI 
16f0be0a1fSXin LI extern int caseless;
1795270f73SXin LI extern int is_caseless;
18b7780dbeSXin LI extern int utf_mode;
19f0be0a1fSXin LI 
20f0be0a1fSXin LI /*
21f0be0a1fSXin LI  * Compile a search pattern, for future use by match_pattern.
22f0be0a1fSXin LI  */
23*c77c4889SXin LI static int compile_pattern2(constant char *pattern, int search_type, PATTERN_TYPE *comp_pattern, int show_error)
24f0be0a1fSXin LI {
2596e55cc7SXin LI 	if (search_type & SRCH_NO_REGEX)
2696e55cc7SXin LI 		return (0);
27f0be0a1fSXin LI   {
2896e55cc7SXin LI #if HAVE_GNU_REGEX
2996e55cc7SXin LI 	struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
3096e55cc7SXin LI 		ecalloc(1, sizeof(struct re_pattern_buffer));
3196e55cc7SXin LI 	re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
3296e55cc7SXin LI 	if (re_compile_pattern(pattern, strlen(pattern), comp))
3396e55cc7SXin LI 	{
3496e55cc7SXin LI 		free(comp);
35a15691bfSXin LI 		if (show_error)
3696e55cc7SXin LI 			error("Invalid pattern", NULL_PARG);
3796e55cc7SXin LI 		return (-1);
3896e55cc7SXin LI 	}
39f6b74a7dSXin LI 	if (*comp_pattern != NULL)
40f6b74a7dSXin LI 	{
41f6b74a7dSXin LI 		regfree(*comp_pattern);
42f6b74a7dSXin LI 		free(*comp_pattern);
43f6b74a7dSXin LI 	}
44f6b74a7dSXin LI 	*comp_pattern = comp;
4596e55cc7SXin LI #endif
46f0be0a1fSXin LI #if HAVE_POSIX_REGCOMP
47f0be0a1fSXin LI 	regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
4895270f73SXin LI 	if (regcomp(comp, pattern, REGCOMP_FLAG | (is_caseless ? REG_ICASE : 0)))
49f0be0a1fSXin LI 	{
50f0be0a1fSXin LI 		free(comp);
51a15691bfSXin LI 		if (show_error)
52f0be0a1fSXin LI 			error("Invalid pattern", NULL_PARG);
53f0be0a1fSXin LI 		return (-1);
54f0be0a1fSXin LI 	}
55f6b74a7dSXin LI 	if (*comp_pattern != NULL)
56f6b74a7dSXin LI 	{
57f6b74a7dSXin LI 		regfree(*comp_pattern);
58f6b74a7dSXin LI 		free(*comp_pattern);
59f6b74a7dSXin LI 	}
60f6b74a7dSXin LI 	*comp_pattern = comp;
61f0be0a1fSXin LI #endif
62f0be0a1fSXin LI #if HAVE_PCRE
6396e55cc7SXin LI 	constant char *errstring;
64f0be0a1fSXin LI 	int erroffset;
65f0be0a1fSXin LI 	PARG parg;
66b7780dbeSXin LI 	pcre *comp = pcre_compile(pattern,
6795270f73SXin LI 			((utf_mode) ? PCRE_UTF8 | PCRE_NO_UTF8_CHECK : 0) |
6895270f73SXin LI 			(is_caseless ? PCRE_CASELESS : 0),
69f0be0a1fSXin LI 			&errstring, &erroffset, NULL);
70f0be0a1fSXin LI 	if (comp == NULL)
71f0be0a1fSXin LI 	{
72f0be0a1fSXin LI 		parg.p_string = (char *) errstring;
73a15691bfSXin LI 		if (show_error)
74f0be0a1fSXin LI 			error("%s", &parg);
75f0be0a1fSXin LI 		return (-1);
76f0be0a1fSXin LI 	}
77f6b74a7dSXin LI 	*comp_pattern = comp;
78f0be0a1fSXin LI #endif
79b7780dbeSXin LI #if HAVE_PCRE2
80b7780dbeSXin LI 	int errcode;
81b7780dbeSXin LI 	PCRE2_SIZE erroffset;
82b7780dbeSXin LI 	PARG parg;
83b7780dbeSXin LI 	pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern),
8495270f73SXin LI 			(is_caseless ? PCRE2_CASELESS : 0),
8595270f73SXin LI 			&errcode, &erroffset, NULL);
86b7780dbeSXin LI 	if (comp == NULL)
87b7780dbeSXin LI 	{
88b7780dbeSXin LI 		if (show_error)
89b7780dbeSXin LI 		{
90b7780dbeSXin LI 			char msg[160];
91b7780dbeSXin LI 			pcre2_get_error_message(errcode, (PCRE2_UCHAR*)msg, sizeof(msg));
92b7780dbeSXin LI 			parg.p_string = msg;
93b7780dbeSXin LI 			error("%s", &parg);
94b7780dbeSXin LI 		}
95b7780dbeSXin LI 		return (-1);
96b7780dbeSXin LI 	}
97b7780dbeSXin LI 	*comp_pattern = comp;
98b7780dbeSXin LI #endif
99f0be0a1fSXin LI #if HAVE_RE_COMP
100f0be0a1fSXin LI 	PARG parg;
101f0be0a1fSXin LI 	if ((parg.p_string = re_comp(pattern)) != NULL)
102f0be0a1fSXin LI 	{
103a15691bfSXin LI 		if (show_error)
104f0be0a1fSXin LI 			error("%s", &parg);
105f0be0a1fSXin LI 		return (-1);
106f0be0a1fSXin LI 	}
107f6b74a7dSXin LI 	*comp_pattern = 1;
108f0be0a1fSXin LI #endif
109f0be0a1fSXin LI #if HAVE_REGCMP
110f0be0a1fSXin LI 	char *comp;
111f0be0a1fSXin LI 	if ((comp = regcmp(pattern, 0)) == NULL)
112f0be0a1fSXin LI 	{
113a15691bfSXin LI 		if (show_error)
114f0be0a1fSXin LI 			error("Invalid pattern", NULL_PARG);
115f0be0a1fSXin LI 		return (-1);
116f0be0a1fSXin LI 	}
117f6b74a7dSXin LI 	if (comp_pattern != NULL)
118f6b74a7dSXin LI 		free(*comp_pattern);
119f6b74a7dSXin LI 	*comp_pattern = comp;
120f0be0a1fSXin LI #endif
121f0be0a1fSXin LI #if HAVE_V8_REGCOMP
122f0be0a1fSXin LI 	struct regexp *comp;
123a15691bfSXin LI 	reg_show_error = show_error;
124a15691bfSXin LI 	comp = regcomp(pattern);
125a15691bfSXin LI 	reg_show_error = 1;
126a15691bfSXin LI 	if (comp == NULL)
127f0be0a1fSXin LI 	{
128f0be0a1fSXin LI 		/*
129f0be0a1fSXin LI 		 * regcomp has already printed an error message
130f0be0a1fSXin LI 		 * via regerror().
131f0be0a1fSXin LI 		 */
132f0be0a1fSXin LI 		return (-1);
133f0be0a1fSXin LI 	}
134f6b74a7dSXin LI 	if (*comp_pattern != NULL)
135f6b74a7dSXin LI 		free(*comp_pattern);
136f6b74a7dSXin LI 	*comp_pattern = comp;
137f0be0a1fSXin LI #endif
138f0be0a1fSXin LI   }
139f0be0a1fSXin LI 	return (0);
140f0be0a1fSXin LI }
141f0be0a1fSXin LI 
142f0be0a1fSXin LI /*
143f0be0a1fSXin LI  * Like compile_pattern2, but convert the pattern to lowercase if necessary.
144f0be0a1fSXin LI  */
145*c77c4889SXin LI public int compile_pattern(constant char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)
146f0be0a1fSXin LI {
147f0be0a1fSXin LI 	int result;
148f0be0a1fSXin LI 
149d713e089SXin LI 	if (caseless != OPT_ONPLUS || (re_handles_caseless && !(search_type & SRCH_NO_REGEX)))
150f0be0a1fSXin LI 	{
151*c77c4889SXin LI 		result = compile_pattern2(pattern, search_type, comp_pattern, show_error);
152*c77c4889SXin LI 	} else
153*c77c4889SXin LI 	{
154*c77c4889SXin LI 		char *cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
155*c77c4889SXin LI 		cvt_text(cvt_pattern, pattern, NULL, NULL, CVT_TO_LC);
1562235c7feSXin LI 		result = compile_pattern2(cvt_pattern, search_type, comp_pattern, show_error);
157f0be0a1fSXin LI 		free(cvt_pattern);
158*c77c4889SXin LI 	}
159f0be0a1fSXin LI 	return (result);
160f0be0a1fSXin LI }
161f0be0a1fSXin LI 
162f0be0a1fSXin LI /*
163f0be0a1fSXin LI  * Forget that we have a compiled pattern.
164f0be0a1fSXin LI  */
165d713e089SXin LI public void uncompile_pattern(PATTERN_TYPE *pattern)
166f0be0a1fSXin LI {
16796e55cc7SXin LI #if HAVE_GNU_REGEX
168f6b74a7dSXin LI 	if (*pattern != NULL)
169f6b74a7dSXin LI 	{
170f6b74a7dSXin LI 		regfree(*pattern);
171f6b74a7dSXin LI 		free(*pattern);
172f6b74a7dSXin LI 	}
173f6b74a7dSXin LI 	*pattern = NULL;
17496e55cc7SXin LI #endif
175f0be0a1fSXin LI #if HAVE_POSIX_REGCOMP
176f6b74a7dSXin LI 	if (*pattern != NULL)
177f6b74a7dSXin LI 	{
178f6b74a7dSXin LI 		regfree(*pattern);
179f6b74a7dSXin LI 		free(*pattern);
180f6b74a7dSXin LI 	}
181f6b74a7dSXin LI 	*pattern = NULL;
182f0be0a1fSXin LI #endif
183f0be0a1fSXin LI #if HAVE_PCRE
184f6b74a7dSXin LI 	if (*pattern != NULL)
185f6b74a7dSXin LI 		pcre_free(*pattern);
186f6b74a7dSXin LI 	*pattern = NULL;
187f0be0a1fSXin LI #endif
188b7780dbeSXin LI #if HAVE_PCRE2
189b7780dbeSXin LI 	if (*pattern != NULL)
190b7780dbeSXin LI 		pcre2_code_free(*pattern);
191b7780dbeSXin LI 	*pattern = NULL;
192b7780dbeSXin LI #endif
193f0be0a1fSXin LI #if HAVE_RE_COMP
194f6b74a7dSXin LI 	*pattern = 0;
195f0be0a1fSXin LI #endif
196f0be0a1fSXin LI #if HAVE_REGCMP
197f6b74a7dSXin LI 	if (*pattern != NULL)
198f6b74a7dSXin LI 		free(*pattern);
199f6b74a7dSXin LI 	*pattern = NULL;
200f0be0a1fSXin LI #endif
201f0be0a1fSXin LI #if HAVE_V8_REGCOMP
202f6b74a7dSXin LI 	if (*pattern != NULL)
203f6b74a7dSXin LI 		free(*pattern);
204f6b74a7dSXin LI 	*pattern = NULL;
205f0be0a1fSXin LI #endif
206f0be0a1fSXin LI }
207f0be0a1fSXin LI 
2082235c7feSXin LI #if 0
209f0be0a1fSXin LI /*
210a15691bfSXin LI  * Can a pattern be successfully compiled?
211a15691bfSXin LI  */
212d713e089SXin LI public int valid_pattern(char *pattern)
213a15691bfSXin LI {
214f6b74a7dSXin LI 	PATTERN_TYPE comp_pattern;
215a15691bfSXin LI 	int result;
216a15691bfSXin LI 
2172235c7feSXin LI 	SET_NULL_PATTERN(comp_pattern);
218a15691bfSXin LI 	result = compile_pattern2(pattern, 0, &comp_pattern, 0);
219a15691bfSXin LI 	if (result != 0)
220a15691bfSXin LI 		return (0);
221a15691bfSXin LI 	uncompile_pattern(&comp_pattern);
222a15691bfSXin LI 	return (1);
223a15691bfSXin LI }
2242235c7feSXin LI #endif
225a15691bfSXin LI 
226a15691bfSXin LI /*
227f0be0a1fSXin LI  * Is a compiled pattern null?
228f0be0a1fSXin LI  */
229*c77c4889SXin LI public lbool is_null_pattern(PATTERN_TYPE pattern)
230f0be0a1fSXin LI {
23196e55cc7SXin LI #if HAVE_GNU_REGEX
23296e55cc7SXin LI 	return (pattern == NULL);
23396e55cc7SXin LI #endif
234f0be0a1fSXin LI #if HAVE_POSIX_REGCOMP
235f0be0a1fSXin LI 	return (pattern == NULL);
236f0be0a1fSXin LI #endif
237f0be0a1fSXin LI #if HAVE_PCRE
238f0be0a1fSXin LI 	return (pattern == NULL);
239f0be0a1fSXin LI #endif
240b7780dbeSXin LI #if HAVE_PCRE2
241b7780dbeSXin LI 	return (pattern == NULL);
242b7780dbeSXin LI #endif
243f0be0a1fSXin LI #if HAVE_RE_COMP
244f0be0a1fSXin LI 	return (pattern == 0);
245f0be0a1fSXin LI #endif
246f0be0a1fSXin LI #if HAVE_REGCMP
247f0be0a1fSXin LI 	return (pattern == NULL);
248f0be0a1fSXin LI #endif
249f0be0a1fSXin LI #if HAVE_V8_REGCOMP
250f0be0a1fSXin LI 	return (pattern == NULL);
251f0be0a1fSXin LI #endif
252a15691bfSXin LI #if NO_REGEX
253a15691bfSXin LI 	return (pattern == NULL);
254a15691bfSXin LI #endif
255f0be0a1fSXin LI }
256f0be0a1fSXin LI /*
257f0be0a1fSXin LI  * Simple pattern matching function.
258f0be0a1fSXin LI  * It supports no metacharacters like *, etc.
259f0be0a1fSXin LI  */
260*c77c4889SXin LI static int match(constant char *pattern, size_t pattern_len, constant char *buf, int buf_len, constant char ***sp, constant char ***ep, int nsubs)
261f0be0a1fSXin LI {
262*c77c4889SXin LI 	constant char *pp;
263*c77c4889SXin LI 	constant char *lp;
264*c77c4889SXin LI 	constant char *pattern_end = pattern + pattern_len;
265*c77c4889SXin LI 	constant char *buf_end = buf + buf_len;
266f0be0a1fSXin LI 
267*c77c4889SXin LI 	(void) nsubs;
268f0be0a1fSXin LI 	for ( ;  buf < buf_end;  buf++)
269f0be0a1fSXin LI 	{
270a15691bfSXin LI 		for (pp = pattern, lp = buf;  ;  pp++, lp++)
271a15691bfSXin LI 		{
272a15691bfSXin LI 			char cp = *pp;
273a15691bfSXin LI 			char cl = *lp;
274a15691bfSXin LI 			if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
275a15691bfSXin LI 				cp = ASCII_TO_LOWER(cp);
276a15691bfSXin LI 			if (cp != cl)
277a15691bfSXin LI 				break;
278f0be0a1fSXin LI 			if (pp == pattern_end || lp == buf_end)
279f0be0a1fSXin LI 				break;
280a15691bfSXin LI 		}
281f0be0a1fSXin LI 		if (pp == pattern_end)
282f0be0a1fSXin LI 		{
283d713e089SXin LI 			*(*sp)++ = buf;
284d713e089SXin LI 			*(*ep)++ = lp;
285f0be0a1fSXin LI 			return (1);
286f0be0a1fSXin LI 		}
287f0be0a1fSXin LI 	}
288d713e089SXin LI 	**sp = **ep = NULL;
289f0be0a1fSXin LI 	return (0);
290f0be0a1fSXin LI }
291f0be0a1fSXin LI 
292f0be0a1fSXin LI /*
293f0be0a1fSXin LI  * Perform a pattern match with the previously compiled pattern.
294d713e089SXin LI  * Set sp[0] and ep[0] to the start and end of the matched string.
295d713e089SXin LI  * Set sp[i] and ep[i] to the start and end of the i-th matched subpattern.
296d713e089SXin LI  * Subpatterns are defined by parentheses in the regex language.
297f0be0a1fSXin LI  */
298*c77c4889SXin LI static int match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t aline_len, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
299f0be0a1fSXin LI {
300f0be0a1fSXin LI 	int matched;
301*c77c4889SXin LI 	int line_len = (int) aline_len; /*{{type-issue}}*/
302f0be0a1fSXin LI 
30396e55cc7SXin LI #if NO_REGEX
30496e55cc7SXin LI 	search_type |= SRCH_NO_REGEX;
30596e55cc7SXin LI #endif
306f0be0a1fSXin LI 	if (search_type & SRCH_NO_REGEX)
307d713e089SXin LI 		matched = match(tpattern, strlen(tpattern), line, line_len, &sp, &ep, nsp);
308f0be0a1fSXin LI 	else
309f0be0a1fSXin LI 	{
31096e55cc7SXin LI #if HAVE_GNU_REGEX
31196e55cc7SXin LI 	{
31296e55cc7SXin LI 		struct re_registers search_regs;
313f6b74a7dSXin LI 		pattern->not_bol = notbol;
314f6b74a7dSXin LI 		pattern->regs_allocated = REGS_UNALLOCATED;
315f6b74a7dSXin LI 		matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0;
31696e55cc7SXin LI 		if (matched)
31796e55cc7SXin LI 		{
318d713e089SXin LI 			*sp++ = line + search_regs.start[0];
319d713e089SXin LI 			*ep++ = line + search_regs.end[0];
32096e55cc7SXin LI 		}
32196e55cc7SXin LI 	}
32296e55cc7SXin LI #endif
323f0be0a1fSXin LI #if HAVE_POSIX_REGCOMP
324f0be0a1fSXin LI 	{
325d713e089SXin LI 		#define RM_COUNT (NUM_SEARCH_COLORS+2)
326d713e089SXin LI 		regmatch_t rm[RM_COUNT];
327f0be0a1fSXin LI 		int flags = (notbol) ? REG_NOTBOL : 0;
328a15691bfSXin LI #ifdef REG_STARTEND
329a15691bfSXin LI 		flags |= REG_STARTEND;
330d713e089SXin LI 		rm[0].rm_so = 0;
331d713e089SXin LI 		rm[0].rm_eo = line_len;
332a15691bfSXin LI #endif
333d713e089SXin LI 		matched = !regexec(pattern, line, RM_COUNT, rm, flags);
334f0be0a1fSXin LI 		if (matched)
335f0be0a1fSXin LI 		{
336d713e089SXin LI 			int i;
337d713e089SXin LI 			int ecount;
338d713e089SXin LI 			for (ecount = RM_COUNT;  ecount > 0;  ecount--)
339d713e089SXin LI 				if (rm[ecount-1].rm_so >= 0)
340d713e089SXin LI 					break;
341d713e089SXin LI 			if (ecount >= nsp)
342d713e089SXin LI 				ecount = nsp-1;
343d713e089SXin LI 			for (i = 0;  i < ecount;  i++)
344d713e089SXin LI 			{
345d713e089SXin LI 				if (rm[i].rm_so < 0)
346d713e089SXin LI 				{
347d713e089SXin LI 					*sp++ = *ep++ = line;
348d713e089SXin LI 				} else
349d713e089SXin LI 				{
350f0be0a1fSXin LI #ifndef __WATCOMC__
351d713e089SXin LI 					*sp++ = line + rm[i].rm_so;
352d713e089SXin LI 					*ep++ = line + rm[i].rm_eo;
353f0be0a1fSXin LI #else
354d713e089SXin LI 					*sp++ = rm[i].rm_sp;
355d713e089SXin LI 					*ep++ = rm[i].rm_ep;
356f0be0a1fSXin LI #endif
357f0be0a1fSXin LI 				}
358f0be0a1fSXin LI 			}
359d713e089SXin LI 		}
360d713e089SXin LI 	}
361f0be0a1fSXin LI #endif
362f0be0a1fSXin LI #if HAVE_PCRE
363f0be0a1fSXin LI 	{
364d713e089SXin LI 		#define OVECTOR_COUNT ((3*NUM_SEARCH_COLORS)+3)
365d713e089SXin LI 		int ovector[OVECTOR_COUNT];
366f0be0a1fSXin LI 		int flags = (notbol) ? PCRE_NOTBOL : 0;
367d713e089SXin LI 		int i;
368d713e089SXin LI 		int ecount;
369d713e089SXin LI 		int mcount = pcre_exec(pattern, NULL, line, line_len,
370d713e089SXin LI 			0, flags, ovector, OVECTOR_COUNT);
371d713e089SXin LI 		matched = (mcount > 0);
372d713e089SXin LI 		ecount = nsp-1;
373d713e089SXin LI 		if (ecount > mcount) ecount = mcount;
374d713e089SXin LI 		for (i = 0;  i < ecount*2; )
375f0be0a1fSXin LI 		{
376d713e089SXin LI 			if (ovector[i] < 0 || ovector[i+1] < 0)
377d713e089SXin LI 			{
378d713e089SXin LI 				*sp++ = *ep++ = line;
379d713e089SXin LI 				i += 2;
380d713e089SXin LI 			} else
381d713e089SXin LI 			{
382d713e089SXin LI 				*sp++ = line + ovector[i++];
383d713e089SXin LI 				*ep++ = line + ovector[i++];
384d713e089SXin LI 			}
385f0be0a1fSXin LI 		}
386f0be0a1fSXin LI 	}
387f0be0a1fSXin LI #endif
388b7780dbeSXin LI #if HAVE_PCRE2
389b7780dbeSXin LI 	{
390b7780dbeSXin LI 		int flags = (notbol) ? PCRE2_NOTBOL : 0;
391d713e089SXin LI 		pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL);
392d713e089SXin LI 		int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len,
393d713e089SXin LI 			0, flags, md, NULL);
394d713e089SXin LI 		matched = (mcount > 0);
395b7780dbeSXin LI 		if (matched)
396b7780dbeSXin LI 		{
397b7780dbeSXin LI 			PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md);
398d713e089SXin LI 			int i;
399d713e089SXin LI 			int ecount = nsp-1;
400d713e089SXin LI 			if (ecount > mcount) ecount = mcount;
401d713e089SXin LI 			for (i = 0;  i < ecount*2; )
402d713e089SXin LI 			{
403d713e089SXin LI 				if (ovector[i] < 0 || ovector[i+1] < 0)
404d713e089SXin LI 				{
405d713e089SXin LI 					*sp++ = *ep++ = line;
406d713e089SXin LI 					i += 2;
407d713e089SXin LI 				} else
408d713e089SXin LI 				{
409d713e089SXin LI 					*sp++ = line + ovector[i++];
410d713e089SXin LI 					*ep++ = line + ovector[i++];
411d713e089SXin LI 				}
412d713e089SXin LI 			}
413b7780dbeSXin LI 		}
414b7780dbeSXin LI 		pcre2_match_data_free(md);
415b7780dbeSXin LI 	}
416b7780dbeSXin LI #endif
417f0be0a1fSXin LI #if HAVE_RE_COMP
418f0be0a1fSXin LI 	matched = (re_exec(line) == 1);
419f0be0a1fSXin LI 	/*
420f0be0a1fSXin LI 	 * re_exec doesn't seem to provide a way to get the matched string.
421f0be0a1fSXin LI 	 */
422f0be0a1fSXin LI #endif
423f0be0a1fSXin LI #if HAVE_REGCMP
424d713e089SXin LI 	matched = ((*ep++ = regex(pattern, line)) != NULL);
425f0be0a1fSXin LI 	if (matched)
426d713e089SXin LI 		*sp++ = __loc1;
427f0be0a1fSXin LI #endif
428f0be0a1fSXin LI #if HAVE_V8_REGCOMP
429f0be0a1fSXin LI #if HAVE_REGEXEC2
430f6b74a7dSXin LI 	matched = regexec2(pattern, line, notbol);
431f0be0a1fSXin LI #else
432f6b74a7dSXin LI 	matched = regexec(pattern, line);
433f0be0a1fSXin LI #endif
434f0be0a1fSXin LI 	if (matched)
435f0be0a1fSXin LI 	{
436d713e089SXin LI 		*sp++ = pattern->startp[0];
437d713e089SXin LI 		*ep++ = pattern->endp[0];
438f0be0a1fSXin LI 	}
439f0be0a1fSXin LI #endif
440f0be0a1fSXin LI 	}
441d713e089SXin LI 	*sp = *ep = NULL;
442f0be0a1fSXin LI 	matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
443f0be0a1fSXin LI 			((search_type & SRCH_NO_MATCH) && !matched);
444f0be0a1fSXin LI 	return (matched);
445f0be0a1fSXin LI }
446f0be0a1fSXin LI 
447*c77c4889SXin LI public int match_pattern(PATTERN_TYPE pattern, constant char *tpattern, constant char *line, size_t line_len, constant char **sp, constant char **ep, int nsp, int notbol, int search_type)
448d713e089SXin LI {
449d713e089SXin LI 	int matched = match_pattern1(pattern, tpattern, line, line_len, sp, ep, nsp, notbol, search_type);
450d713e089SXin LI 	int i;
451d713e089SXin LI 	for (i = 1;  i <= NUM_SEARCH_COLORS;  i++)
452d713e089SXin LI 	{
453d713e089SXin LI 		if ((search_type & SRCH_SUBSEARCH(i)) && ep[i] == sp[i])
454d713e089SXin LI 			matched = 0;
455d713e089SXin LI 	}
456d713e089SXin LI 	return matched;
457d713e089SXin LI }
458d713e089SXin LI 
459b7780dbeSXin LI /*
460b7780dbeSXin LI  * Return the name of the pattern matching library.
461b7780dbeSXin LI  */
462*c77c4889SXin LI public constant char * pattern_lib_name(void)
463b7780dbeSXin LI {
464b7780dbeSXin LI #if HAVE_GNU_REGEX
465b7780dbeSXin LI 	return ("GNU");
466b7780dbeSXin LI #else
467b7780dbeSXin LI #if HAVE_POSIX_REGCOMP
468b7780dbeSXin LI 	return ("POSIX");
469b7780dbeSXin LI #else
470b7780dbeSXin LI #if HAVE_PCRE2
471b7780dbeSXin LI 	return ("PCRE2");
472b7780dbeSXin LI #else
473b7780dbeSXin LI #if HAVE_PCRE
474b7780dbeSXin LI 	return ("PCRE");
475b7780dbeSXin LI #else
476b7780dbeSXin LI #if HAVE_RE_COMP
477b7780dbeSXin LI 	return ("BSD");
478b7780dbeSXin LI #else
479b7780dbeSXin LI #if HAVE_REGCMP
480b7780dbeSXin LI 	return ("V8");
481b7780dbeSXin LI #else
482b7780dbeSXin LI #if HAVE_V8_REGCOMP
483b7780dbeSXin LI 	return ("Spencer V8");
484b7780dbeSXin LI #else
485b7780dbeSXin LI 	return ("no");
486b7780dbeSXin LI #endif
487b7780dbeSXin LI #endif
488b7780dbeSXin LI #endif
489b7780dbeSXin LI #endif
490b7780dbeSXin LI #endif
491b7780dbeSXin LI #endif
492b7780dbeSXin LI #endif
493b7780dbeSXin LI }
494