1*838f5788Ssimonb /* $NetBSD: pattern.c,v 1.4 2023/10/06 05:49:49 simonb Exp $ */
220006a0bStron
320006a0bStron /*
4*838f5788Ssimonb * Copyright (C) 1984-2023 Mark Nudelman
520006a0bStron *
620006a0bStron * You may distribute under the terms of either the GNU General Public
720006a0bStron * License or the Less License, as specified in the README file.
820006a0bStron *
9ec18bca0Stron * For more information, see the README file.
1020006a0bStron */
1120006a0bStron
1220006a0bStron /*
1320006a0bStron * Routines to do pattern matching.
1420006a0bStron */
1520006a0bStron
1620006a0bStron #include "less.h"
1720006a0bStron
1820006a0bStron extern int caseless;
19*838f5788Ssimonb extern int is_caseless;
20*838f5788Ssimonb extern int utf_mode;
2120006a0bStron
2220006a0bStron /*
2320006a0bStron * Compile a search pattern, for future use by match_pattern.
2420006a0bStron */
compile_pattern2(char * pattern,int search_type,PATTERN_TYPE * comp_pattern,int show_error)25*838f5788Ssimonb static int compile_pattern2(char *pattern, int search_type, PATTERN_TYPE *comp_pattern, int show_error)
2620006a0bStron {
27ec18bca0Stron if (search_type & SRCH_NO_REGEX)
28ec18bca0Stron return (0);
2920006a0bStron {
30ec18bca0Stron #if HAVE_GNU_REGEX
31ec18bca0Stron struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
32ec18bca0Stron ecalloc(1, sizeof(struct re_pattern_buffer));
33ec18bca0Stron re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
34ec18bca0Stron if (re_compile_pattern(pattern, strlen(pattern), comp))
35ec18bca0Stron {
36ec18bca0Stron free(comp);
37*838f5788Ssimonb if (show_error)
38ec18bca0Stron error("Invalid pattern", NULL_PARG);
39ec18bca0Stron return (-1);
40ec18bca0Stron }
41*838f5788Ssimonb if (*comp_pattern != NULL)
42*838f5788Ssimonb {
43*838f5788Ssimonb regfree(*comp_pattern);
44*838f5788Ssimonb free(*comp_pattern);
45*838f5788Ssimonb }
46*838f5788Ssimonb *comp_pattern = comp;
47ec18bca0Stron #endif
4820006a0bStron #if HAVE_POSIX_REGCOMP
4920006a0bStron regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
50*838f5788Ssimonb if (regcomp(comp, pattern, REGCOMP_FLAG | (is_caseless ? REG_ICASE : 0)))
5120006a0bStron {
5220006a0bStron free(comp);
53*838f5788Ssimonb if (show_error)
5420006a0bStron error("Invalid pattern", NULL_PARG);
5520006a0bStron return (-1);
5620006a0bStron }
57*838f5788Ssimonb if (*comp_pattern != NULL)
58*838f5788Ssimonb {
59*838f5788Ssimonb regfree(*comp_pattern);
60*838f5788Ssimonb free(*comp_pattern);
61*838f5788Ssimonb }
62*838f5788Ssimonb *comp_pattern = comp;
6320006a0bStron #endif
6420006a0bStron #if HAVE_PCRE
65ec18bca0Stron constant char *errstring;
6620006a0bStron int erroffset;
6720006a0bStron PARG parg;
68*838f5788Ssimonb pcre *comp = pcre_compile(pattern,
69*838f5788Ssimonb ((utf_mode) ? PCRE_UTF8 | PCRE_NO_UTF8_CHECK : 0) |
70*838f5788Ssimonb (is_caseless ? PCRE_CASELESS : 0),
7120006a0bStron &errstring, &erroffset, NULL);
7220006a0bStron if (comp == NULL)
7320006a0bStron {
7420006a0bStron parg.p_string = (char *) errstring;
75*838f5788Ssimonb if (show_error)
7620006a0bStron error("%s", &parg);
7720006a0bStron return (-1);
7820006a0bStron }
79*838f5788Ssimonb *comp_pattern = comp;
80*838f5788Ssimonb #endif
81*838f5788Ssimonb #if HAVE_PCRE2
82*838f5788Ssimonb int errcode;
83*838f5788Ssimonb PCRE2_SIZE erroffset;
84*838f5788Ssimonb PARG parg;
85*838f5788Ssimonb pcre2_code *comp = pcre2_compile((PCRE2_SPTR)pattern, strlen(pattern),
86*838f5788Ssimonb (is_caseless ? PCRE2_CASELESS : 0),
87*838f5788Ssimonb &errcode, &erroffset, NULL);
88*838f5788Ssimonb if (comp == NULL)
89*838f5788Ssimonb {
90*838f5788Ssimonb if (show_error)
91*838f5788Ssimonb {
92*838f5788Ssimonb char msg[160];
93*838f5788Ssimonb pcre2_get_error_message(errcode, (PCRE2_UCHAR*)msg, sizeof(msg));
94*838f5788Ssimonb parg.p_string = msg;
95*838f5788Ssimonb error("%s", &parg);
96*838f5788Ssimonb }
97*838f5788Ssimonb return (-1);
98*838f5788Ssimonb }
99*838f5788Ssimonb *comp_pattern = comp;
10020006a0bStron #endif
10120006a0bStron #if HAVE_RE_COMP
10220006a0bStron PARG parg;
10320006a0bStron if ((parg.p_string = re_comp(pattern)) != NULL)
10420006a0bStron {
105*838f5788Ssimonb if (show_error)
10620006a0bStron error("%s", &parg);
10720006a0bStron return (-1);
10820006a0bStron }
109*838f5788Ssimonb *comp_pattern = 1;
11020006a0bStron #endif
11120006a0bStron #if HAVE_REGCMP
11220006a0bStron char *comp;
11320006a0bStron if ((comp = regcmp(pattern, 0)) == NULL)
11420006a0bStron {
115*838f5788Ssimonb if (show_error)
11620006a0bStron error("Invalid pattern", NULL_PARG);
11720006a0bStron return (-1);
11820006a0bStron }
119*838f5788Ssimonb if (comp_pattern != NULL)
120*838f5788Ssimonb free(*comp_pattern);
121*838f5788Ssimonb *comp_pattern = comp;
12220006a0bStron #endif
12320006a0bStron #if HAVE_V8_REGCOMP
12420006a0bStron struct regexp *comp;
125*838f5788Ssimonb reg_show_error = show_error;
126*838f5788Ssimonb comp = regcomp(pattern);
127*838f5788Ssimonb reg_show_error = 1;
128*838f5788Ssimonb if (comp == NULL)
12920006a0bStron {
13020006a0bStron /*
13120006a0bStron * regcomp has already printed an error message
13220006a0bStron * via regerror().
13320006a0bStron */
13420006a0bStron return (-1);
13520006a0bStron }
136*838f5788Ssimonb if (*comp_pattern != NULL)
137*838f5788Ssimonb free(*comp_pattern);
138*838f5788Ssimonb *comp_pattern = comp;
13920006a0bStron #endif
14020006a0bStron }
14120006a0bStron return (0);
14220006a0bStron }
14320006a0bStron
14420006a0bStron /*
14520006a0bStron * Like compile_pattern2, but convert the pattern to lowercase if necessary.
14620006a0bStron */
compile_pattern(char * pattern,int search_type,int show_error,PATTERN_TYPE * comp_pattern)147*838f5788Ssimonb public int compile_pattern(char *pattern, int search_type, int show_error, PATTERN_TYPE *comp_pattern)
14820006a0bStron {
14920006a0bStron char *cvt_pattern;
15020006a0bStron int result;
15120006a0bStron
152*838f5788Ssimonb if (caseless != OPT_ONPLUS || (re_handles_caseless && !(search_type & SRCH_NO_REGEX)))
15320006a0bStron cvt_pattern = pattern;
15420006a0bStron else
15520006a0bStron {
15620006a0bStron cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
15720006a0bStron cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC);
15820006a0bStron }
159*838f5788Ssimonb result = compile_pattern2(cvt_pattern, search_type, comp_pattern, show_error);
16020006a0bStron if (cvt_pattern != pattern)
16120006a0bStron free(cvt_pattern);
16220006a0bStron return (result);
16320006a0bStron }
16420006a0bStron
16520006a0bStron /*
16620006a0bStron * Forget that we have a compiled pattern.
16720006a0bStron */
uncompile_pattern(PATTERN_TYPE * pattern)168*838f5788Ssimonb public void uncompile_pattern(PATTERN_TYPE *pattern)
16920006a0bStron {
170ec18bca0Stron #if HAVE_GNU_REGEX
171*838f5788Ssimonb if (*pattern != NULL)
172*838f5788Ssimonb {
173*838f5788Ssimonb regfree(*pattern);
174*838f5788Ssimonb free(*pattern);
175*838f5788Ssimonb }
176*838f5788Ssimonb *pattern = NULL;
177ec18bca0Stron #endif
17820006a0bStron #if HAVE_POSIX_REGCOMP
179*838f5788Ssimonb if (*pattern != NULL)
180*838f5788Ssimonb {
181*838f5788Ssimonb regfree(*pattern);
182*838f5788Ssimonb free(*pattern);
183*838f5788Ssimonb }
184*838f5788Ssimonb *pattern = NULL;
18520006a0bStron #endif
18620006a0bStron #if HAVE_PCRE
187*838f5788Ssimonb if (*pattern != NULL)
188*838f5788Ssimonb pcre_free(*pattern);
189*838f5788Ssimonb *pattern = NULL;
190*838f5788Ssimonb #endif
191*838f5788Ssimonb #if HAVE_PCRE2
192*838f5788Ssimonb if (*pattern != NULL)
193*838f5788Ssimonb pcre2_code_free(*pattern);
194*838f5788Ssimonb *pattern = NULL;
19520006a0bStron #endif
19620006a0bStron #if HAVE_RE_COMP
197*838f5788Ssimonb *pattern = 0;
19820006a0bStron #endif
19920006a0bStron #if HAVE_REGCMP
200*838f5788Ssimonb if (*pattern != NULL)
201*838f5788Ssimonb free(*pattern);
202*838f5788Ssimonb *pattern = NULL;
20320006a0bStron #endif
20420006a0bStron #if HAVE_V8_REGCOMP
205*838f5788Ssimonb if (*pattern != NULL)
206*838f5788Ssimonb free(*pattern);
207*838f5788Ssimonb *pattern = NULL;
20820006a0bStron #endif
20920006a0bStron }
21020006a0bStron
211*838f5788Ssimonb #if 0
212*838f5788Ssimonb /*
213*838f5788Ssimonb * Can a pattern be successfully compiled?
214*838f5788Ssimonb */
215*838f5788Ssimonb public int valid_pattern(char *pattern)
216*838f5788Ssimonb {
217*838f5788Ssimonb PATTERN_TYPE comp_pattern;
218*838f5788Ssimonb int result;
219*838f5788Ssimonb
220*838f5788Ssimonb SET_NULL_PATTERN(comp_pattern);
221*838f5788Ssimonb result = compile_pattern2(pattern, 0, &comp_pattern, 0);
222*838f5788Ssimonb if (result != 0)
223*838f5788Ssimonb return (0);
224*838f5788Ssimonb uncompile_pattern(&comp_pattern);
225*838f5788Ssimonb return (1);
226*838f5788Ssimonb }
227*838f5788Ssimonb #endif
228*838f5788Ssimonb
22920006a0bStron /*
23020006a0bStron * Is a compiled pattern null?
23120006a0bStron */
is_null_pattern(PATTERN_TYPE pattern)232*838f5788Ssimonb public int is_null_pattern(PATTERN_TYPE pattern)
23320006a0bStron {
234ec18bca0Stron #if HAVE_GNU_REGEX
235ec18bca0Stron return (pattern == NULL);
236ec18bca0Stron #endif
23720006a0bStron #if HAVE_POSIX_REGCOMP
23820006a0bStron return (pattern == NULL);
23920006a0bStron #endif
24020006a0bStron #if HAVE_PCRE
24120006a0bStron return (pattern == NULL);
24220006a0bStron #endif
243*838f5788Ssimonb #if HAVE_PCRE2
244*838f5788Ssimonb return (pattern == NULL);
245*838f5788Ssimonb #endif
24620006a0bStron #if HAVE_RE_COMP
24720006a0bStron return (pattern == 0);
24820006a0bStron #endif
24920006a0bStron #if HAVE_REGCMP
25020006a0bStron return (pattern == NULL);
25120006a0bStron #endif
25220006a0bStron #if HAVE_V8_REGCOMP
25320006a0bStron return (pattern == NULL);
25420006a0bStron #endif
255*838f5788Ssimonb #if NO_REGEX
256*838f5788Ssimonb return (pattern == NULL);
257*838f5788Ssimonb #endif
25820006a0bStron }
25920006a0bStron /*
26020006a0bStron * Simple pattern matching function.
26120006a0bStron * It supports no metacharacters like *, etc.
26220006a0bStron */
match(char * pattern,int pattern_len,char * buf,int buf_len,char *** sp,char *** ep,int nsubs)263*838f5788Ssimonb static int match(char *pattern, int pattern_len, char *buf, int buf_len, char ***sp, char ***ep, int nsubs)
26420006a0bStron {
265*838f5788Ssimonb char *pp, *lp;
266*838f5788Ssimonb char *pattern_end = pattern + pattern_len;
267*838f5788Ssimonb char *buf_end = buf + buf_len;
26820006a0bStron
26920006a0bStron for ( ; buf < buf_end; buf++)
27020006a0bStron {
271*838f5788Ssimonb for (pp = pattern, lp = buf; ; pp++, lp++)
272*838f5788Ssimonb {
273*838f5788Ssimonb char cp = *pp;
274*838f5788Ssimonb char cl = *lp;
275*838f5788Ssimonb if (caseless == OPT_ONPLUS && ASCII_IS_UPPER(cp))
276*838f5788Ssimonb cp = ASCII_TO_LOWER(cp);
277*838f5788Ssimonb if (cp != cl)
278*838f5788Ssimonb break;
27920006a0bStron if (pp == pattern_end || lp == buf_end)
28020006a0bStron break;
281*838f5788Ssimonb }
28220006a0bStron if (pp == pattern_end)
28320006a0bStron {
284*838f5788Ssimonb *(*sp)++ = buf;
285*838f5788Ssimonb *(*ep)++ = lp;
28620006a0bStron return (1);
28720006a0bStron }
28820006a0bStron }
289*838f5788Ssimonb **sp = **ep = NULL;
29020006a0bStron return (0);
29120006a0bStron }
29220006a0bStron
29320006a0bStron /*
29420006a0bStron * Perform a pattern match with the previously compiled pattern.
295*838f5788Ssimonb * Set sp[0] and ep[0] to the start and end of the matched string.
296*838f5788Ssimonb * Set sp[i] and ep[i] to the start and end of the i-th matched subpattern.
297*838f5788Ssimonb * Subpatterns are defined by parentheses in the regex language.
29820006a0bStron */
match_pattern1(PATTERN_TYPE pattern,char * tpattern,char * line,int line_len,char ** sp,char ** ep,int nsp,int notbol,int search_type)299*838f5788Ssimonb static int match_pattern1(PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int nsp, int notbol, int search_type)
30020006a0bStron {
30120006a0bStron int matched;
30220006a0bStron
303ec18bca0Stron #if NO_REGEX
304ec18bca0Stron search_type |= SRCH_NO_REGEX;
305ec18bca0Stron #endif
30620006a0bStron if (search_type & SRCH_NO_REGEX)
307*838f5788Ssimonb matched = match(tpattern, strlen(tpattern), line, line_len, &sp, &ep, nsp);
30820006a0bStron else
30920006a0bStron {
310ec18bca0Stron #if HAVE_GNU_REGEX
311ec18bca0Stron {
312ec18bca0Stron struct re_registers search_regs;
313*838f5788Ssimonb pattern->not_bol = notbol;
314*838f5788Ssimonb pattern->regs_allocated = REGS_UNALLOCATED;
315*838f5788Ssimonb matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0;
316ec18bca0Stron if (matched)
317ec18bca0Stron {
318*838f5788Ssimonb *sp++ = line + search_regs.start[0];
319*838f5788Ssimonb *ep++ = line + search_regs.end[0];
320ec18bca0Stron }
321ec18bca0Stron }
322ec18bca0Stron #endif
32320006a0bStron #if HAVE_POSIX_REGCOMP
32420006a0bStron {
325*838f5788Ssimonb #define RM_COUNT (NUM_SEARCH_COLORS+2)
326*838f5788Ssimonb regmatch_t rm[RM_COUNT];
32720006a0bStron int flags = (notbol) ? REG_NOTBOL : 0;
328*838f5788Ssimonb #ifdef REG_STARTEND
329*838f5788Ssimonb flags |= REG_STARTEND;
330*838f5788Ssimonb rm[0].rm_so = 0;
331*838f5788Ssimonb rm[0].rm_eo = line_len;
332*838f5788Ssimonb #endif
333*838f5788Ssimonb matched = !regexec(pattern, line, RM_COUNT, rm, flags);
33420006a0bStron if (matched)
33520006a0bStron {
336*838f5788Ssimonb int i;
337*838f5788Ssimonb int ecount;
338*838f5788Ssimonb for (ecount = RM_COUNT; ecount > 0; ecount--)
339*838f5788Ssimonb if (rm[ecount-1].rm_so >= 0)
340*838f5788Ssimonb break;
341*838f5788Ssimonb if (ecount >= nsp)
342*838f5788Ssimonb ecount = nsp-1;
343*838f5788Ssimonb for (i = 0; i < ecount; i++)
344*838f5788Ssimonb {
345*838f5788Ssimonb if (rm[i].rm_so < 0)
346*838f5788Ssimonb {
347*838f5788Ssimonb *sp++ = *ep++ = line;
348*838f5788Ssimonb } else
349*838f5788Ssimonb {
35020006a0bStron #ifndef __WATCOMC__
351*838f5788Ssimonb *sp++ = line + rm[i].rm_so;
352*838f5788Ssimonb *ep++ = line + rm[i].rm_eo;
35320006a0bStron #else
354*838f5788Ssimonb *sp++ = rm[i].rm_sp;
355*838f5788Ssimonb *ep++ = rm[i].rm_ep;
35620006a0bStron #endif
35720006a0bStron }
35820006a0bStron }
359*838f5788Ssimonb }
360*838f5788Ssimonb }
36120006a0bStron #endif
36220006a0bStron #if HAVE_PCRE
36320006a0bStron {
364*838f5788Ssimonb #define OVECTOR_COUNT ((3*NUM_SEARCH_COLORS)+3)
365*838f5788Ssimonb int ovector[OVECTOR_COUNT];
36620006a0bStron int flags = (notbol) ? PCRE_NOTBOL : 0;
367*838f5788Ssimonb int i;
368*838f5788Ssimonb int ecount;
369*838f5788Ssimonb int mcount = pcre_exec(pattern, NULL, line, line_len,
370*838f5788Ssimonb 0, flags, ovector, OVECTOR_COUNT);
371*838f5788Ssimonb matched = (mcount > 0);
372*838f5788Ssimonb ecount = nsp-1;
373*838f5788Ssimonb if (ecount > mcount) ecount = mcount;
374*838f5788Ssimonb for (i = 0; i < ecount*2; )
375*838f5788Ssimonb {
376*838f5788Ssimonb if (ovector[i] < 0 || ovector[i+1] < 0)
377*838f5788Ssimonb {
378*838f5788Ssimonb *sp++ = *ep++ = line;
379*838f5788Ssimonb i += 2;
380*838f5788Ssimonb } else
381*838f5788Ssimonb {
382*838f5788Ssimonb *sp++ = line + ovector[i++];
383*838f5788Ssimonb *ep++ = line + ovector[i++];
384*838f5788Ssimonb }
385*838f5788Ssimonb }
386*838f5788Ssimonb }
387*838f5788Ssimonb #endif
388*838f5788Ssimonb #if HAVE_PCRE2
389*838f5788Ssimonb {
390*838f5788Ssimonb int flags = (notbol) ? PCRE2_NOTBOL : 0;
391*838f5788Ssimonb pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL);
392*838f5788Ssimonb int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len,
393*838f5788Ssimonb 0, flags, md, NULL);
394*838f5788Ssimonb matched = (mcount > 0);
39520006a0bStron if (matched)
39620006a0bStron {
397*838f5788Ssimonb PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(md);
398*838f5788Ssimonb int i;
399*838f5788Ssimonb int ecount = nsp-1;
400*838f5788Ssimonb if (ecount > mcount) ecount = mcount;
401*838f5788Ssimonb for (i = 0; i < ecount*2; )
402*838f5788Ssimonb {
403*838f5788Ssimonb if (ovector[i] < 0 || ovector[i+1] < 0)
404*838f5788Ssimonb {
405*838f5788Ssimonb *sp++ = *ep++ = line;
406*838f5788Ssimonb i += 2;
407*838f5788Ssimonb } else
408*838f5788Ssimonb {
409*838f5788Ssimonb *sp++ = line + ovector[i++];
410*838f5788Ssimonb *ep++ = line + ovector[i++];
41120006a0bStron }
41220006a0bStron }
413*838f5788Ssimonb }
414*838f5788Ssimonb pcre2_match_data_free(md);
415*838f5788Ssimonb }
41620006a0bStron #endif
41720006a0bStron #if HAVE_RE_COMP
41820006a0bStron matched = (re_exec(line) == 1);
41920006a0bStron /*
42020006a0bStron * re_exec doesn't seem to provide a way to get the matched string.
42120006a0bStron */
42220006a0bStron #endif
42320006a0bStron #if HAVE_REGCMP
424*838f5788Ssimonb matched = ((*ep++ = regex(pattern, line)) != NULL);
42520006a0bStron if (matched)
426*838f5788Ssimonb *sp++ = __loc1;
42720006a0bStron #endif
42820006a0bStron #if HAVE_V8_REGCOMP
42920006a0bStron #if HAVE_REGEXEC2
430*838f5788Ssimonb matched = regexec2(pattern, line, notbol);
43120006a0bStron #else
432*838f5788Ssimonb matched = regexec(pattern, line);
43320006a0bStron #endif
43420006a0bStron if (matched)
43520006a0bStron {
436*838f5788Ssimonb *sp++ = pattern->startp[0];
437*838f5788Ssimonb *ep++ = pattern->endp[0];
43820006a0bStron }
43920006a0bStron #endif
44020006a0bStron }
441*838f5788Ssimonb *sp = *ep = NULL;
44220006a0bStron matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
44320006a0bStron ((search_type & SRCH_NO_MATCH) && !matched);
44420006a0bStron return (matched);
44520006a0bStron }
44620006a0bStron
match_pattern(PATTERN_TYPE pattern,char * tpattern,char * line,int line_len,char ** sp,char ** ep,int nsp,int notbol,int search_type)447*838f5788Ssimonb public int match_pattern(PATTERN_TYPE pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int nsp, int notbol, int search_type)
448*838f5788Ssimonb {
449*838f5788Ssimonb int matched = match_pattern1(pattern, tpattern, line, line_len, sp, ep, nsp, notbol, search_type);
450*838f5788Ssimonb int i;
451*838f5788Ssimonb for (i = 1; i <= NUM_SEARCH_COLORS; i++)
452*838f5788Ssimonb {
453*838f5788Ssimonb if ((search_type & SRCH_SUBSEARCH(i)) && ep[i] == sp[i])
454*838f5788Ssimonb matched = 0;
455*838f5788Ssimonb }
456*838f5788Ssimonb return matched;
457*838f5788Ssimonb }
458*838f5788Ssimonb
459*838f5788Ssimonb /*
460*838f5788Ssimonb * Return the name of the pattern matching library.
461*838f5788Ssimonb */
pattern_lib_name(void)462*838f5788Ssimonb public char * pattern_lib_name(void)
463*838f5788Ssimonb {
464*838f5788Ssimonb #if HAVE_GNU_REGEX
465*838f5788Ssimonb return ("GNU");
466*838f5788Ssimonb #else
467*838f5788Ssimonb #if HAVE_POSIX_REGCOMP
468*838f5788Ssimonb return ("POSIX");
469*838f5788Ssimonb #else
470*838f5788Ssimonb #if HAVE_PCRE2
471*838f5788Ssimonb return ("PCRE2");
472*838f5788Ssimonb #else
473*838f5788Ssimonb #if HAVE_PCRE
474*838f5788Ssimonb return ("PCRE");
475*838f5788Ssimonb #else
476*838f5788Ssimonb #if HAVE_RE_COMP
477*838f5788Ssimonb return ("BSD");
478*838f5788Ssimonb #else
479*838f5788Ssimonb #if HAVE_REGCMP
480*838f5788Ssimonb return ("V8");
481*838f5788Ssimonb #else
482*838f5788Ssimonb #if HAVE_V8_REGCOMP
483*838f5788Ssimonb return ("Spencer V8");
484*838f5788Ssimonb #else
485*838f5788Ssimonb return ("no");
486*838f5788Ssimonb #endif
487*838f5788Ssimonb #endif
488*838f5788Ssimonb #endif
489*838f5788Ssimonb #endif
490*838f5788Ssimonb #endif
491*838f5788Ssimonb #endif
492*838f5788Ssimonb #endif
493*838f5788Ssimonb }
494