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