xref: /dflybsd-src/contrib/less/pattern.c (revision e0f238eda64c20d98364903e0c003825fd0b66dd)
1a9adbba3SJan Lentfer /*
2*e433da38SAaron LI  * Copyright (C) 1984-2024  Mark Nudelman
3a9adbba3SJan Lentfer  *
4a9adbba3SJan Lentfer  * You may distribute under the terms of either the GNU General Public
5a9adbba3SJan Lentfer  * License or the Less License, as specified in the README file.
6a9adbba3SJan Lentfer  *
7e639dc31SJohn Marino  * For more information, see the README file.
8a9adbba3SJan Lentfer  */
9a9adbba3SJan Lentfer 
10a9adbba3SJan Lentfer /*
11a9adbba3SJan Lentfer  * Routines to do pattern matching.
12a9adbba3SJan Lentfer  */
13a9adbba3SJan Lentfer 
14a9adbba3SJan Lentfer #include "less.h"
15a9adbba3SJan Lentfer 
16a9adbba3SJan Lentfer extern int caseless;
170c7ad07eSAntonio Huete Jimenez extern int is_caseless;
1802d62a0fSDaniel Fojt extern int utf_mode;
19a9adbba3SJan Lentfer 
20a9adbba3SJan Lentfer /*
21a9adbba3SJan Lentfer  * Compile a search pattern, for future use by match_pattern.
22a9adbba3SJan Lentfer  */
compile_pattern2(constant char * pattern,int search_type,PATTERN_TYPE * comp_pattern,int show_error)23*e433da38SAaron LI static int compile_pattern2(constant char *pattern, int search_type, PATTERN_TYPE *comp_pattern, int show_error)
24a9adbba3SJan Lentfer {
25e639dc31SJohn Marino 	if (search_type & SRCH_NO_REGEX)
26e639dc31SJohn Marino 		return (0);
27a9adbba3SJan Lentfer   {
28e639dc31SJohn Marino #if HAVE_GNU_REGEX
29e639dc31SJohn Marino 	struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
30e639dc31SJohn Marino 		ecalloc(1, sizeof(struct re_pattern_buffer));
31e639dc31SJohn Marino 	re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
32e639dc31SJohn Marino 	if (re_compile_pattern(pattern, strlen(pattern), comp))
33e639dc31SJohn Marino 	{
34e639dc31SJohn Marino 		free(comp);
35fa0be7c5SJohn Marino 		if (show_error)
36e639dc31SJohn Marino 			error("Invalid pattern", NULL_PARG);
37e639dc31SJohn Marino 		return (-1);
38e639dc31SJohn Marino 	}
3902d62a0fSDaniel Fojt 	if (*comp_pattern != NULL)
4002d62a0fSDaniel Fojt 	{
4102d62a0fSDaniel Fojt 		regfree(*comp_pattern);
4202d62a0fSDaniel Fojt 		free(*comp_pattern);
4302d62a0fSDaniel Fojt 	}
4402d62a0fSDaniel Fojt 	*comp_pattern = comp;
45e639dc31SJohn Marino #endif
46a9adbba3SJan Lentfer #if HAVE_POSIX_REGCOMP
47a9adbba3SJan Lentfer 	regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
480c7ad07eSAntonio Huete Jimenez 	if (regcomp(comp, pattern, REGCOMP_FLAG | (is_caseless ? REG_ICASE : 0)))
49a9adbba3SJan Lentfer 	{
50a9adbba3SJan Lentfer 		free(comp);
51fa0be7c5SJohn Marino 		if (show_error)
52a9adbba3SJan Lentfer 			error("Invalid pattern", NULL_PARG);
53a9adbba3SJan Lentfer 		return (-1);
54a9adbba3SJan Lentfer 	}
5502d62a0fSDaniel Fojt 	if (*comp_pattern != NULL)
5602d62a0fSDaniel Fojt 	{
5702d62a0fSDaniel Fojt 		regfree(*comp_pattern);
5802d62a0fSDaniel Fojt 		free(*comp_pattern);
5902d62a0fSDaniel Fojt 	}
6002d62a0fSDaniel Fojt 	*comp_pattern = comp;
61a9adbba3SJan Lentfer #endif
62a9adbba3SJan Lentfer #if HAVE_PCRE
63e639dc31SJohn Marino 	constant char *errstring;
64a9adbba3SJan Lentfer 	int erroffset;
65a9adbba3SJan Lentfer 	PARG parg;
6602d62a0fSDaniel Fojt 	pcre *comp = pcre_compile(pattern,
670c7ad07eSAntonio Huete Jimenez 			((utf_mode) ? PCRE_UTF8 | PCRE_NO_UTF8_CHECK : 0) |
680c7ad07eSAntonio Huete Jimenez 			(is_caseless ? PCRE_CASELESS : 0),
69a9adbba3SJan Lentfer 			&errstring, &erroffset, NULL);
70a9adbba3SJan Lentfer 	if (comp == NULL)
71a9adbba3SJan Lentfer 	{
72a9adbba3SJan Lentfer 		parg.p_string = (char *) errstring;
73fa0be7c5SJohn Marino 		if (show_error)
74a9adbba3SJan Lentfer 			error("%s", &parg);
75a9adbba3SJan Lentfer 		return (-1);
76a9adbba3SJan Lentfer 	}
7702d62a0fSDaniel Fojt 	*comp_pattern = comp;
7802d62a0fSDaniel Fojt #endif
7902d62a0fSDaniel Fojt #if HAVE_PCRE2
8002d62a0fSDaniel Fojt 	int errcode;
8102d62a0fSDaniel Fojt 	PCRE2_SIZE erroffset;
8202d62a0fSDaniel Fojt 	PARG parg;
8302d62a0fSDaniel Fojt 	pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern),
840c7ad07eSAntonio Huete Jimenez 			(is_caseless ? PCRE2_CASELESS : 0),
850c7ad07eSAntonio Huete Jimenez 			&errcode, &erroffset, NULL);
8602d62a0fSDaniel Fojt 	if (comp == NULL)
8702d62a0fSDaniel Fojt 	{
8802d62a0fSDaniel Fojt 		if (show_error)
8902d62a0fSDaniel Fojt 		{
9002d62a0fSDaniel Fojt 			char msg[160];
9102d62a0fSDaniel Fojt 			pcre2_get_error_message(errcode, (PCRE2_UCHAR*)msg, sizeof(msg));
9202d62a0fSDaniel Fojt 			parg.p_string = msg;
9302d62a0fSDaniel Fojt 			error("%s", &parg);
9402d62a0fSDaniel Fojt 		}
9502d62a0fSDaniel Fojt 		return (-1);
9602d62a0fSDaniel Fojt 	}
9702d62a0fSDaniel Fojt 	*comp_pattern = comp;
98a9adbba3SJan Lentfer #endif
99a9adbba3SJan Lentfer #if HAVE_RE_COMP
100a9adbba3SJan Lentfer 	PARG parg;
101a9adbba3SJan Lentfer 	if ((parg.p_string = re_comp(pattern)) != NULL)
102a9adbba3SJan Lentfer 	{
103fa0be7c5SJohn Marino 		if (show_error)
104a9adbba3SJan Lentfer 			error("%s", &parg);
105a9adbba3SJan Lentfer 		return (-1);
106a9adbba3SJan Lentfer 	}
10702d62a0fSDaniel Fojt 	*comp_pattern = 1;
108a9adbba3SJan Lentfer #endif
109a9adbba3SJan Lentfer #if HAVE_REGCMP
110a9adbba3SJan Lentfer 	char *comp;
111a9adbba3SJan Lentfer 	if ((comp = regcmp(pattern, 0)) == NULL)
112a9adbba3SJan Lentfer 	{
113fa0be7c5SJohn Marino 		if (show_error)
114a9adbba3SJan Lentfer 			error("Invalid pattern", NULL_PARG);
115a9adbba3SJan Lentfer 		return (-1);
116a9adbba3SJan Lentfer 	}
11702d62a0fSDaniel Fojt 	if (comp_pattern != NULL)
11802d62a0fSDaniel Fojt 		free(*comp_pattern);
11902d62a0fSDaniel Fojt 	*comp_pattern = comp;
120a9adbba3SJan Lentfer #endif
121a9adbba3SJan Lentfer #if HAVE_V8_REGCOMP
122a9adbba3SJan Lentfer 	struct regexp *comp;
123fa0be7c5SJohn Marino 	reg_show_error = show_error;
124fa0be7c5SJohn Marino 	comp = regcomp(pattern);
125fa0be7c5SJohn Marino 	reg_show_error = 1;
126fa0be7c5SJohn Marino 	if (comp == NULL)
127a9adbba3SJan Lentfer 	{
128a9adbba3SJan Lentfer 		/*
129a9adbba3SJan Lentfer 		 * regcomp has already printed an error message
130a9adbba3SJan Lentfer 		 * via regerror().
131a9adbba3SJan Lentfer 		 */
132a9adbba3SJan Lentfer 		return (-1);
133a9adbba3SJan Lentfer 	}
13402d62a0fSDaniel Fojt 	if (*comp_pattern != NULL)
13502d62a0fSDaniel Fojt 		free(*comp_pattern);
13602d62a0fSDaniel Fojt 	*comp_pattern = comp;
137a9adbba3SJan Lentfer #endif
138a9adbba3SJan Lentfer   }
139a9adbba3SJan Lentfer 	return (0);
140a9adbba3SJan Lentfer }
141a9adbba3SJan Lentfer 
142a9adbba3SJan Lentfer /*
143a9adbba3SJan Lentfer  * Like compile_pattern2, but convert the pattern to lowercase if necessary.
144a9adbba3SJan Lentfer  */
compile_pattern(constant char * pattern,int search_type,int show_error,PATTERN_TYPE * comp_pattern)145*e433da38SAaron LI public int compile_pattern(constant char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)
146a9adbba3SJan Lentfer {
147a9adbba3SJan Lentfer 	int result;
148a9adbba3SJan Lentfer 
149320d7c8aSAaron LI 	if (caseless != OPT_ONPLUS || (re_handles_caseless && !(search_type & SRCH_NO_REGEX)))
150a9adbba3SJan Lentfer 	{
151*e433da38SAaron LI 		result = compile_pattern2(pattern, search_type, comp_pattern, show_error);
152*e433da38SAaron LI 	} else
153*e433da38SAaron LI 	{
154*e433da38SAaron LI 		char *cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
155*e433da38SAaron LI 		cvt_text(cvt_pattern, pattern, NULL, NULL, CVT_TO_LC);
1560c7ad07eSAntonio Huete Jimenez 		result = compile_pattern2(cvt_pattern, search_type, comp_pattern, show_error);
157a9adbba3SJan Lentfer 		free(cvt_pattern);
158*e433da38SAaron LI 	}
159a9adbba3SJan Lentfer 	return (result);
160a9adbba3SJan Lentfer }
161a9adbba3SJan Lentfer 
162a9adbba3SJan Lentfer /*
163a9adbba3SJan Lentfer  * Forget that we have a compiled pattern.
164a9adbba3SJan Lentfer  */
uncompile_pattern(PATTERN_TYPE * pattern)165320d7c8aSAaron LI public void uncompile_pattern(PATTERN_TYPE *pattern)
166a9adbba3SJan Lentfer {
167e639dc31SJohn Marino #if HAVE_GNU_REGEX
16802d62a0fSDaniel Fojt 	if (*pattern != NULL)
16902d62a0fSDaniel Fojt 	{
17002d62a0fSDaniel Fojt 		regfree(*pattern);
17102d62a0fSDaniel Fojt 		free(*pattern);
17202d62a0fSDaniel Fojt 	}
17302d62a0fSDaniel Fojt 	*pattern = NULL;
174e639dc31SJohn Marino #endif
175a9adbba3SJan Lentfer #if HAVE_POSIX_REGCOMP
17602d62a0fSDaniel Fojt 	if (*pattern != NULL)
17702d62a0fSDaniel Fojt 	{
17802d62a0fSDaniel Fojt 		regfree(*pattern);
17902d62a0fSDaniel Fojt 		free(*pattern);
18002d62a0fSDaniel Fojt 	}
18102d62a0fSDaniel Fojt 	*pattern = NULL;
182a9adbba3SJan Lentfer #endif
183a9adbba3SJan Lentfer #if HAVE_PCRE
18402d62a0fSDaniel Fojt 	if (*pattern != NULL)
18502d62a0fSDaniel Fojt 		pcre_free(*pattern);
18602d62a0fSDaniel Fojt 	*pattern = NULL;
18702d62a0fSDaniel Fojt #endif
18802d62a0fSDaniel Fojt #if HAVE_PCRE2
18902d62a0fSDaniel Fojt 	if (*pattern != NULL)
19002d62a0fSDaniel Fojt 		pcre2_code_free(*pattern);
19102d62a0fSDaniel Fojt 	*pattern = NULL;
192a9adbba3SJan Lentfer #endif
193a9adbba3SJan Lentfer #if HAVE_RE_COMP
19402d62a0fSDaniel Fojt 	*pattern = 0;
195a9adbba3SJan Lentfer #endif
196a9adbba3SJan Lentfer #if HAVE_REGCMP
19702d62a0fSDaniel Fojt 	if (*pattern != NULL)
19802d62a0fSDaniel Fojt 		free(*pattern);
19902d62a0fSDaniel Fojt 	*pattern = NULL;
200a9adbba3SJan Lentfer #endif
201a9adbba3SJan Lentfer #if HAVE_V8_REGCOMP
20202d62a0fSDaniel Fojt 	if (*pattern != NULL)
20302d62a0fSDaniel Fojt 		free(*pattern);
20402d62a0fSDaniel Fojt 	*pattern = NULL;
205a9adbba3SJan Lentfer #endif
206a9adbba3SJan Lentfer }
207a9adbba3SJan Lentfer 
2080c7ad07eSAntonio Huete Jimenez #if 0
209a9adbba3SJan Lentfer /*
210fa0be7c5SJohn Marino  * Can a pattern be successfully compiled?
211fa0be7c5SJohn Marino  */
212320d7c8aSAaron LI public int valid_pattern(char *pattern)
213fa0be7c5SJohn Marino {
21402d62a0fSDaniel Fojt 	PATTERN_TYPE comp_pattern;
215fa0be7c5SJohn Marino 	int result;
216fa0be7c5SJohn Marino 
2170c7ad07eSAntonio Huete Jimenez 	SET_NULL_PATTERN(comp_pattern);
218fa0be7c5SJohn Marino 	result = compile_pattern2(pattern, 0, &comp_pattern, 0);
219fa0be7c5SJohn Marino 	if (result != 0)
220fa0be7c5SJohn Marino 		return (0);
221fa0be7c5SJohn Marino 	uncompile_pattern(&comp_pattern);
222fa0be7c5SJohn Marino 	return (1);
223fa0be7c5SJohn Marino }
2240c7ad07eSAntonio Huete Jimenez #endif
225fa0be7c5SJohn Marino 
226fa0be7c5SJohn Marino /*
227a9adbba3SJan Lentfer  * Is a compiled pattern null?
228a9adbba3SJan Lentfer  */
is_null_pattern(PATTERN_TYPE pattern)229*e433da38SAaron LI public lbool is_null_pattern(PATTERN_TYPE pattern)
230a9adbba3SJan Lentfer {
231e639dc31SJohn Marino #if HAVE_GNU_REGEX
232e639dc31SJohn Marino 	return (pattern == NULL);
233e639dc31SJohn Marino #endif
234a9adbba3SJan Lentfer #if HAVE_POSIX_REGCOMP
235a9adbba3SJan Lentfer 	return (pattern == NULL);
236a9adbba3SJan Lentfer #endif
237a9adbba3SJan Lentfer #if HAVE_PCRE
238a9adbba3SJan Lentfer 	return (pattern == NULL);
239a9adbba3SJan Lentfer #endif
24002d62a0fSDaniel Fojt #if HAVE_PCRE2
24102d62a0fSDaniel Fojt 	return (pattern == NULL);
24202d62a0fSDaniel Fojt #endif
243a9adbba3SJan Lentfer #if HAVE_RE_COMP
244a9adbba3SJan Lentfer 	return (pattern == 0);
245a9adbba3SJan Lentfer #endif
246a9adbba3SJan Lentfer #if HAVE_REGCMP
247a9adbba3SJan Lentfer 	return (pattern == NULL);
248a9adbba3SJan Lentfer #endif
249a9adbba3SJan Lentfer #if HAVE_V8_REGCOMP
250a9adbba3SJan Lentfer 	return (pattern == NULL);
251a9adbba3SJan Lentfer #endif
2529b760066SJohn Marino #if NO_REGEX
2539b760066SJohn Marino 	return (pattern == NULL);
2549b760066SJohn Marino #endif
255a9adbba3SJan Lentfer }
256a9adbba3SJan Lentfer /*
257a9adbba3SJan Lentfer  * Simple pattern matching function.
258a9adbba3SJan Lentfer  * It supports no metacharacters like *, etc.
259a9adbba3SJan Lentfer  */
match(constant char * pattern,size_t pattern_len,constant char * buf,int buf_len,constant char *** sp,constant char *** ep,int nsubs)260*e433da38SAaron 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)
261a9adbba3SJan Lentfer {
262*e433da38SAaron LI 	constant char *pp;
263*e433da38SAaron LI 	constant char *lp;
264*e433da38SAaron LI 	constant char *pattern_end = pattern + pattern_len;
265*e433da38SAaron LI 	constant char *buf_end = buf + buf_len;
266a9adbba3SJan Lentfer 
267*e433da38SAaron LI 	(void) nsubs;
268a9adbba3SJan Lentfer 	for ( ;  buf < buf_end;  buf++)
269a9adbba3SJan Lentfer 	{
2709b760066SJohn Marino 		for (pp = pattern, lp = buf;  ;  pp++, lp++)
2719b760066SJohn Marino 		{
2729b760066SJohn Marino 			char cp = *pp;
2739b760066SJohn Marino 			char cl = *lp;
2749b760066SJohn Marino 			if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
2759b760066SJohn Marino 				cp = ASCII_TO_LOWER(cp);
2769b760066SJohn Marino 			if (cp != cl)
2779b760066SJohn Marino 				break;
278a9adbba3SJan Lentfer 			if (pp == pattern_end || lp == buf_end)
279a9adbba3SJan Lentfer 				break;
2809b760066SJohn Marino 		}
281a9adbba3SJan Lentfer 		if (pp == pattern_end)
282a9adbba3SJan Lentfer 		{
283320d7c8aSAaron LI 			*(*sp)++ = buf;
284320d7c8aSAaron LI 			*(*ep)++ = lp;
285a9adbba3SJan Lentfer 			return (1);
286a9adbba3SJan Lentfer 		}
287a9adbba3SJan Lentfer 	}
288320d7c8aSAaron LI 	**sp = **ep = NULL;
289a9adbba3SJan Lentfer 	return (0);
290a9adbba3SJan Lentfer }
291a9adbba3SJan Lentfer 
292a9adbba3SJan Lentfer /*
293a9adbba3SJan Lentfer  * Perform a pattern match with the previously compiled pattern.
294320d7c8aSAaron LI  * Set sp[0] and ep[0] to the start and end of the matched string.
295320d7c8aSAaron LI  * Set sp[i] and ep[i] to the start and end of the i-th matched subpattern.
296320d7c8aSAaron LI  * Subpatterns are defined by parentheses in the regex language.
297a9adbba3SJan Lentfer  */
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)298*e433da38SAaron 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)
299a9adbba3SJan Lentfer {
300a9adbba3SJan Lentfer 	int matched;
301*e433da38SAaron LI 	int line_len = (int) aline_len; /*{{type-issue}}*/
302a9adbba3SJan Lentfer 
303e639dc31SJohn Marino #if NO_REGEX
304e639dc31SJohn Marino 	search_type |= SRCH_NO_REGEX;
305e639dc31SJohn Marino #endif
306a9adbba3SJan Lentfer 	if (search_type & SRCH_NO_REGEX)
307320d7c8aSAaron LI 		matched = match(tpattern, strlen(tpattern), line, line_len, &sp, &ep, nsp);
308a9adbba3SJan Lentfer 	else
309a9adbba3SJan Lentfer 	{
310e639dc31SJohn Marino #if HAVE_GNU_REGEX
311e639dc31SJohn Marino 	{
312e639dc31SJohn Marino 		struct re_registers search_regs;
31302d62a0fSDaniel Fojt 		pattern->not_bol = notbol;
31402d62a0fSDaniel Fojt 		pattern->regs_allocated = REGS_UNALLOCATED;
31502d62a0fSDaniel Fojt 		matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0;
316e639dc31SJohn Marino 		if (matched)
317e639dc31SJohn Marino 		{
318320d7c8aSAaron LI 			*sp++ = line + search_regs.start[0];
319320d7c8aSAaron LI 			*ep++ = line + search_regs.end[0];
320e639dc31SJohn Marino 		}
321e639dc31SJohn Marino 	}
322e639dc31SJohn Marino #endif
323a9adbba3SJan Lentfer #if HAVE_POSIX_REGCOMP
324a9adbba3SJan Lentfer 	{
325320d7c8aSAaron LI 		#define RM_COUNT (NUM_SEARCH_COLORS+2)
326320d7c8aSAaron LI 		regmatch_t rm[RM_COUNT];
327a9adbba3SJan Lentfer 		int flags = (notbol) ? REG_NOTBOL : 0;
328fa0be7c5SJohn Marino #ifdef REG_STARTEND
329fa0be7c5SJohn Marino 		flags |= REG_STARTEND;
330320d7c8aSAaron LI 		rm[0].rm_so = 0;
331320d7c8aSAaron LI 		rm[0].rm_eo = line_len;
332fa0be7c5SJohn Marino #endif
333320d7c8aSAaron LI 		matched = !regexec(pattern, line, RM_COUNT, rm, flags);
334a9adbba3SJan Lentfer 		if (matched)
335a9adbba3SJan Lentfer 		{
336320d7c8aSAaron LI 			int i;
337320d7c8aSAaron LI 			int ecount;
338320d7c8aSAaron LI 			for (ecount = RM_COUNT;  ecount > 0;  ecount--)
339320d7c8aSAaron LI 				if (rm[ecount-1].rm_so >= 0)
340320d7c8aSAaron LI 					break;
341320d7c8aSAaron LI 			if (ecount >= nsp)
342320d7c8aSAaron LI 				ecount = nsp-1;
343320d7c8aSAaron LI 			for (i = 0;  i < ecount;  i++)
344320d7c8aSAaron LI 			{
345320d7c8aSAaron LI 				if (rm[i].rm_so < 0)
346320d7c8aSAaron LI 				{
347320d7c8aSAaron LI 					*sp++ = *ep++ = line;
348320d7c8aSAaron LI 				} else
349320d7c8aSAaron LI 				{
350a9adbba3SJan Lentfer #ifndef __WATCOMC__
351320d7c8aSAaron LI 					*sp++ = line + rm[i].rm_so;
352320d7c8aSAaron LI 					*ep++ = line + rm[i].rm_eo;
353a9adbba3SJan Lentfer #else
354320d7c8aSAaron LI 					*sp++ = rm[i].rm_sp;
355320d7c8aSAaron LI 					*ep++ = rm[i].rm_ep;
356a9adbba3SJan Lentfer #endif
357a9adbba3SJan Lentfer 				}
358a9adbba3SJan Lentfer 			}
359320d7c8aSAaron LI 		}
360320d7c8aSAaron LI 	}
361a9adbba3SJan Lentfer #endif
362a9adbba3SJan Lentfer #if HAVE_PCRE
363a9adbba3SJan Lentfer 	{
364320d7c8aSAaron LI 		#define OVECTOR_COUNT ((3*NUM_SEARCH_COLORS)+3)
365320d7c8aSAaron LI 		int ovector[OVECTOR_COUNT];
366a9adbba3SJan Lentfer 		int flags = (notbol) ? PCRE_NOTBOL : 0;
367320d7c8aSAaron LI 		int i;
368320d7c8aSAaron LI 		int ecount;
369320d7c8aSAaron LI 		int mcount = pcre_exec(pattern, NULL, line, line_len,
370320d7c8aSAaron LI 			0, flags, ovector, OVECTOR_COUNT);
371320d7c8aSAaron LI 		matched = (mcount > 0);
372320d7c8aSAaron LI 		ecount = nsp-1;
373320d7c8aSAaron LI 		if (ecount > mcount) ecount = mcount;
374320d7c8aSAaron LI 		for (i = 0;  i < ecount*2; )
375a9adbba3SJan Lentfer 		{
376320d7c8aSAaron LI 			if (ovector[i] < 0 || ovector[i+1] < 0)
377320d7c8aSAaron LI 			{
378320d7c8aSAaron LI 				*sp++ = *ep++ = line;
379320d7c8aSAaron LI 				i += 2;
380320d7c8aSAaron LI 			} else
381320d7c8aSAaron LI 			{
382320d7c8aSAaron LI 				*sp++ = line + ovector[i++];
383320d7c8aSAaron LI 				*ep++ = line + ovector[i++];
384320d7c8aSAaron LI 			}
385a9adbba3SJan Lentfer 		}
386a9adbba3SJan Lentfer 	}
387a9adbba3SJan Lentfer #endif
38802d62a0fSDaniel Fojt #if HAVE_PCRE2
38902d62a0fSDaniel Fojt 	{
39002d62a0fSDaniel Fojt 		int flags = (notbol) ? PCRE2_NOTBOL : 0;
391320d7c8aSAaron LI 		pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL);
392320d7c8aSAaron LI 		int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len,
393320d7c8aSAaron LI 			0, flags, md, NULL);
394320d7c8aSAaron LI 		matched = (mcount > 0);
39502d62a0fSDaniel Fojt 		if (matched)
39602d62a0fSDaniel Fojt 		{
39702d62a0fSDaniel Fojt 			PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md);
398320d7c8aSAaron LI 			int i;
399320d7c8aSAaron LI 			int ecount = nsp-1;
400320d7c8aSAaron LI 			if (ecount > mcount) ecount = mcount;
401320d7c8aSAaron LI 			for (i = 0;  i < ecount*2; )
402320d7c8aSAaron LI 			{
403320d7c8aSAaron LI 				if (ovector[i] < 0 || ovector[i+1] < 0)
404320d7c8aSAaron LI 				{
405320d7c8aSAaron LI 					*sp++ = *ep++ = line;
406320d7c8aSAaron LI 					i += 2;
407320d7c8aSAaron LI 				} else
408320d7c8aSAaron LI 				{
409320d7c8aSAaron LI 					*sp++ = line + ovector[i++];
410320d7c8aSAaron LI 					*ep++ = line + ovector[i++];
411320d7c8aSAaron LI 				}
412320d7c8aSAaron LI 			}
41302d62a0fSDaniel Fojt 		}
41402d62a0fSDaniel Fojt 		pcre2_match_data_free(md);
41502d62a0fSDaniel Fojt 	}
41602d62a0fSDaniel Fojt #endif
417a9adbba3SJan Lentfer #if HAVE_RE_COMP
418a9adbba3SJan Lentfer 	matched = (re_exec(line) == 1);
419a9adbba3SJan Lentfer 	/*
420a9adbba3SJan Lentfer 	 * re_exec doesn't seem to provide a way to get the matched string.
421a9adbba3SJan Lentfer 	 */
422a9adbba3SJan Lentfer #endif
423a9adbba3SJan Lentfer #if HAVE_REGCMP
424320d7c8aSAaron LI 	matched = ((*ep++ = regex(pattern, line)) != NULL);
425a9adbba3SJan Lentfer 	if (matched)
426320d7c8aSAaron LI 		*sp++ = __loc1;
427a9adbba3SJan Lentfer #endif
428a9adbba3SJan Lentfer #if HAVE_V8_REGCOMP
429a9adbba3SJan Lentfer #if HAVE_REGEXEC2
43002d62a0fSDaniel Fojt 	matched = regexec2(pattern, line, notbol);
431a9adbba3SJan Lentfer #else
43202d62a0fSDaniel Fojt 	matched = regexec(pattern, line);
433a9adbba3SJan Lentfer #endif
434a9adbba3SJan Lentfer 	if (matched)
435a9adbba3SJan Lentfer 	{
436320d7c8aSAaron LI 		*sp++ = pattern->startp[0];
437320d7c8aSAaron LI 		*ep++ = pattern->endp[0];
438a9adbba3SJan Lentfer 	}
439a9adbba3SJan Lentfer #endif
440a9adbba3SJan Lentfer 	}
441320d7c8aSAaron LI 	*sp = *ep = NULL;
442a9adbba3SJan Lentfer 	matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
443a9adbba3SJan Lentfer 			((search_type & SRCH_NO_MATCH) && !matched);
444a9adbba3SJan Lentfer 	return (matched);
445a9adbba3SJan Lentfer }
446a9adbba3SJan Lentfer 
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)447*e433da38SAaron 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)
448320d7c8aSAaron LI {
449320d7c8aSAaron LI 	int matched = match_pattern1(pattern, tpattern, line, line_len, sp, ep, nsp, notbol, search_type);
450320d7c8aSAaron LI 	int i;
451320d7c8aSAaron LI 	for (i = 1;  i <= NUM_SEARCH_COLORS;  i++)
452320d7c8aSAaron LI 	{
453320d7c8aSAaron LI 		if ((search_type & SRCH_SUBSEARCH(i)) && ep[i] == sp[i])
454320d7c8aSAaron LI 			matched = 0;
455320d7c8aSAaron LI 	}
456320d7c8aSAaron LI 	return matched;
457320d7c8aSAaron LI }
458320d7c8aSAaron LI 
45902d62a0fSDaniel Fojt /*
46002d62a0fSDaniel Fojt  * Return the name of the pattern matching library.
46102d62a0fSDaniel Fojt  */
pattern_lib_name(void)462*e433da38SAaron LI public constant char * pattern_lib_name(void)
46302d62a0fSDaniel Fojt {
46402d62a0fSDaniel Fojt #if HAVE_GNU_REGEX
46502d62a0fSDaniel Fojt 	return ("GNU");
46602d62a0fSDaniel Fojt #else
46702d62a0fSDaniel Fojt #if HAVE_POSIX_REGCOMP
46802d62a0fSDaniel Fojt 	return ("POSIX");
46902d62a0fSDaniel Fojt #else
47002d62a0fSDaniel Fojt #if HAVE_PCRE2
47102d62a0fSDaniel Fojt 	return ("PCRE2");
47202d62a0fSDaniel Fojt #else
47302d62a0fSDaniel Fojt #if HAVE_PCRE
47402d62a0fSDaniel Fojt 	return ("PCRE");
47502d62a0fSDaniel Fojt #else
47602d62a0fSDaniel Fojt #if HAVE_RE_COMP
47702d62a0fSDaniel Fojt 	return ("BSD");
47802d62a0fSDaniel Fojt #else
47902d62a0fSDaniel Fojt #if HAVE_REGCMP
48002d62a0fSDaniel Fojt 	return ("V8");
48102d62a0fSDaniel Fojt #else
48202d62a0fSDaniel Fojt #if HAVE_V8_REGCOMP
48302d62a0fSDaniel Fojt 	return ("Spencer V8");
48402d62a0fSDaniel Fojt #else
48502d62a0fSDaniel Fojt 	return ("no");
48602d62a0fSDaniel Fojt #endif
48702d62a0fSDaniel Fojt #endif
48802d62a0fSDaniel Fojt #endif
48902d62a0fSDaniel Fojt #endif
49002d62a0fSDaniel Fojt #endif
49102d62a0fSDaniel Fojt #endif
49202d62a0fSDaniel Fojt #endif
49302d62a0fSDaniel Fojt }
494