blob: 19c7eda8f57ab82cdb74f8925eab34dceb8d2598 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Regex and string management functions.
3 *
Willy Tarreauf4f04122010-01-28 18:10:50 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <stdlib.h>
15#include <string.h>
16
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020017#include <haproxy/api.h>
Willy Tarreau36979d92020-06-05 17:27:29 +020018#include <haproxy/errors.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +020019#include <haproxy/global.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +020020#include <haproxy/regex.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020021#include <haproxy/tools.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020022
23/* regex trash buffer used by various regex tests */
Emeric Brun272e2522017-06-15 11:53:49 +020024THREAD_LOCAL regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreauc8746532014-05-28 23:05:07 +020026int exp_replace(char *dst, unsigned int dst_size, char *src, const char *str, const regmatch_t *matches)
Willy Tarreaubaaee002006-06-26 02:48:02 +020027{
28 char *old_dst = dst;
Sasha Pachevc6002042014-05-26 12:33:48 -060029 char* dst_end = dst + dst_size;
Willy Tarreaubaaee002006-06-26 02:48:02 +020030
31 while (*str) {
32 if (*str == '\\') {
33 str++;
Sasha Pachevc6002042014-05-26 12:33:48 -060034 if (!*str)
35 return -1;
36
Willy Tarreau8f8e6452007-06-17 21:51:38 +020037 if (isdigit((unsigned char)*str)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +020038 int len, num;
39
40 num = *str - '0';
41 str++;
42
43 if (matches[num].rm_eo > -1 && matches[num].rm_so > -1) {
44 len = matches[num].rm_eo - matches[num].rm_so;
Sasha Pachevc6002042014-05-26 12:33:48 -060045
46 if (dst + len >= dst_end)
47 return -1;
48
Willy Tarreaubaaee002006-06-26 02:48:02 +020049 memcpy(dst, src + matches[num].rm_so, len);
50 dst += len;
51 }
52
53 } else if (*str == 'x') {
54 unsigned char hex1, hex2;
55 str++;
56
Sasha Pachevc6002042014-05-26 12:33:48 -060057 if (!*str)
58 return -1;
59
Willy Tarreauf278eec2020-07-05 21:46:32 +020060 hex1 = toupper((unsigned char)*str++) - '0';
Sasha Pachevc6002042014-05-26 12:33:48 -060061
62 if (!*str)
63 return -1;
64
Willy Tarreauf278eec2020-07-05 21:46:32 +020065 hex2 = toupper((unsigned char)*str++) - '0';
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
68 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
Sasha Pachevc6002042014-05-26 12:33:48 -060069
70 if (dst >= dst_end)
71 return -1;
72
Willy Tarreaubaaee002006-06-26 02:48:02 +020073 *dst++ = (hex1<<4) + hex2;
74 } else {
Sasha Pachevc6002042014-05-26 12:33:48 -060075 if (dst >= dst_end)
76 return -1;
77
Willy Tarreaubaaee002006-06-26 02:48:02 +020078 *dst++ = *str++;
79 }
80 } else {
Sasha Pachevc6002042014-05-26 12:33:48 -060081 if (dst >= dst_end)
82 return -1;
83
Willy Tarreaubaaee002006-06-26 02:48:02 +020084 *dst++ = *str++;
85 }
86 }
Sasha Pachevc6002042014-05-26 12:33:48 -060087 if (dst >= dst_end)
88 return -1;
89
Willy Tarreaubaaee002006-06-26 02:48:02 +020090 *dst = '\0';
91 return dst - old_dst;
92}
93
94/* returns NULL if the replacement string <str> is valid, or the pointer to the first error */
Willy Tarreaub17916e2006-10-15 15:17:57 +020095const char *check_replace_string(const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +020096{
Willy Tarreaub17916e2006-10-15 15:17:57 +020097 const char *err = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +020098 while (*str) {
99 if (*str == '\\') {
100 err = str; /* in case of a backslash, we return the pointer to it */
101 str++;
102 if (!*str)
103 return err;
Willy Tarreau8f8e6452007-06-17 21:51:38 +0200104 else if (isdigit((unsigned char)*str))
Willy Tarreaubaaee002006-06-26 02:48:02 +0200105 err = NULL;
106 else if (*str == 'x') {
107 str++;
108 if (!ishex(*str))
109 return err;
110 str++;
111 if (!ishex(*str))
112 return err;
113 err = NULL;
114 }
115 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100116 ha_warning("'\\%c' : deprecated use of a backslash before something not '\\','x' or a digit.\n", *str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117 err = NULL;
118 }
119 }
120 str++;
121 }
122 return err;
123}
124
125
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200126/* This function apply regex. It take const null terminated char as input.
127 * If the function doesn't match, it returns false, else it returns true.
128 * When it is compiled with JIT, this function execute strlen on the subject.
Willy Tarreau15a53a42015-01-21 13:39:42 +0100129 * Currently the only supported flag is REG_NOTBOL.
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200130 */
131int regex_exec_match(const struct my_regex *preg, const char *subject,
Willy Tarreau15a53a42015-01-21 13:39:42 +0100132 size_t nmatch, regmatch_t pmatch[], int flags) {
David Carlierf2592b22016-11-21 21:25:58 +0000133#if defined(USE_PCRE) || defined(USE_PCRE_JIT) || defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200134 int ret;
David Carlierf2592b22016-11-21 21:25:58 +0000135#ifdef USE_PCRE2
136 PCRE2_SIZE *matches;
137 pcre2_match_data *pm;
138#else
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200139 int matches[MAX_MATCH * 3];
David Carlierf2592b22016-11-21 21:25:58 +0000140#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200141 int enmatch;
142 int i;
Willy Tarreau15a53a42015-01-21 13:39:42 +0100143 int options;
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200144
145 /* Silently limit the number of allowed matches. max
146 * match i the maximum value for match, in fact this
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500147 * limit is not applied.
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200148 */
David Carlierf2592b22016-11-21 21:25:58 +0000149
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200150 enmatch = nmatch;
151 if (enmatch > MAX_MATCH)
152 enmatch = MAX_MATCH;
153
Willy Tarreau15a53a42015-01-21 13:39:42 +0100154 options = 0;
155 if (flags & REG_NOTBOL)
David Carlierf2592b22016-11-21 21:25:58 +0000156#ifdef USE_PCRE2
157 options |= PCRE2_NOTBOL;
158#else
Willy Tarreau15a53a42015-01-21 13:39:42 +0100159 options |= PCRE_NOTBOL;
David Carlierf2592b22016-11-21 21:25:58 +0000160#endif
Willy Tarreau15a53a42015-01-21 13:39:42 +0100161
David Carlierf2592b22016-11-21 21:25:58 +0000162 /* The value returned by pcre_exec()/pcre2_match() is one more than the highest numbered
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200163 * pair that has been set. For example, if two substrings have been captured,
164 * the returned value is 3. If there are no capturing subpatterns, the return
165 * value from a successful match is 1, indicating that just the first pair of
166 * offsets has been set.
167 *
Joseph Herlanteda75482018-11-15 14:46:29 -0800168 * It seems that this function returns 0 if it detects more matches than available
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200169 * space in the matches array.
170 */
David Carlierf2592b22016-11-21 21:25:58 +0000171#ifdef USE_PCRE2
172 pm = pcre2_match_data_create_from_pattern(preg->reg, NULL);
David Carlier7adf8f32020-08-13 14:53:41 +0100173 ret = preg->mfn(preg->reg, (PCRE2_SPTR)subject, (PCRE2_SIZE)strlen(subject), 0, options, pm, NULL);
David Carlierf2592b22016-11-21 21:25:58 +0000174
175 if (ret < 0) {
176 pcre2_match_data_free(pm);
177 return 0;
178 }
179
180 matches = pcre2_get_ovector_pointer(pm);
181#else
Willy Tarreau15a53a42015-01-21 13:39:42 +0100182 ret = pcre_exec(preg->reg, preg->extra, subject, strlen(subject), 0, options, matches, enmatch * 3);
David Carlierf2592b22016-11-21 21:25:58 +0000183
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200184 if (ret < 0)
185 return 0;
David Carlierf2592b22016-11-21 21:25:58 +0000186#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200187
188 if (ret == 0)
189 ret = enmatch;
190
191 for (i=0; i<nmatch; i++) {
192 /* Copy offset. */
193 if (i < ret) {
194 pmatch[i].rm_so = matches[(i*2)];
195 pmatch[i].rm_eo = matches[(i*2)+1];
196 continue;
197 }
198 /* Set the unmatvh flag (-1). */
199 pmatch[i].rm_so = -1;
200 pmatch[i].rm_eo = -1;
201 }
David Carlierf2592b22016-11-21 21:25:58 +0000202#ifdef USE_PCRE2
203 pcre2_match_data_free(pm);
204#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200205 return 1;
206#else
207 int match;
Willy Tarreau15a53a42015-01-21 13:39:42 +0100208
209 flags &= REG_NOTBOL;
210 match = regexec(&preg->regex, subject, nmatch, pmatch, flags);
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200211 if (match == REG_NOMATCH)
212 return 0;
213 return 1;
214#endif
215}
216
217/* This function apply regex. It take a "char *" ans length as input. The
218 * <subject> can be modified during the processing. If the function doesn't
219 * match, it returns false, else it returns true.
220 * When it is compiled with standard POSIX regex or PCRE, this function add
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500221 * a temporary null characters at the end of the <subject>. The <subject> must
Willy Tarreau15a53a42015-01-21 13:39:42 +0100222 * have a real length of <length> + 1. Currently the only supported flag is
223 * REG_NOTBOL.
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200224 */
225int regex_exec_match2(const struct my_regex *preg, char *subject, int length,
Willy Tarreau15a53a42015-01-21 13:39:42 +0100226 size_t nmatch, regmatch_t pmatch[], int flags) {
David Carlierf2592b22016-11-21 21:25:58 +0000227#if defined(USE_PCRE) || defined(USE_PCRE_JIT) || defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200228 int ret;
David Carlierf2592b22016-11-21 21:25:58 +0000229#ifdef USE_PCRE2
230 PCRE2_SIZE *matches;
231 pcre2_match_data *pm;
232#else
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200233 int matches[MAX_MATCH * 3];
David Carlierf2592b22016-11-21 21:25:58 +0000234#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200235 int enmatch;
236 int i;
Willy Tarreau15a53a42015-01-21 13:39:42 +0100237 int options;
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200238
239 /* Silently limit the number of allowed matches. max
240 * match i the maximum value for match, in fact this
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500241 * limit is not applied.
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200242 */
243 enmatch = nmatch;
244 if (enmatch > MAX_MATCH)
245 enmatch = MAX_MATCH;
246
Willy Tarreau15a53a42015-01-21 13:39:42 +0100247 options = 0;
248 if (flags & REG_NOTBOL)
David Carlierf2592b22016-11-21 21:25:58 +0000249#ifdef USE_PCRE2
250 options |= PCRE2_NOTBOL;
251#else
Willy Tarreau15a53a42015-01-21 13:39:42 +0100252 options |= PCRE_NOTBOL;
David Carlierf2592b22016-11-21 21:25:58 +0000253#endif
Willy Tarreau15a53a42015-01-21 13:39:42 +0100254
David Carlier7adf8f32020-08-13 14:53:41 +0100255 /* The value returned by pcre_exec()/pcre2_(jit)_match() is one more than the highest numbered
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200256 * pair that has been set. For example, if two substrings have been captured,
257 * the returned value is 3. If there are no capturing subpatterns, the return
258 * value from a successful match is 1, indicating that just the first pair of
259 * offsets has been set.
260 *
Joseph Herlanteda75482018-11-15 14:46:29 -0800261 * It seems that this function returns 0 if it detects more matches than available
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200262 * space in the matches array.
263 */
David Carlierf2592b22016-11-21 21:25:58 +0000264#ifdef USE_PCRE2
265 pm = pcre2_match_data_create_from_pattern(preg->reg, NULL);
David Carlier7adf8f32020-08-13 14:53:41 +0100266 ret = preg->mfn(preg->reg, (PCRE2_SPTR)subject, (PCRE2_SIZE)length, 0, options, pm, NULL);
David Carlierf2592b22016-11-21 21:25:58 +0000267
268 if (ret < 0) {
269 pcre2_match_data_free(pm);
270 return 0;
271 }
272
273 matches = pcre2_get_ovector_pointer(pm);
274#else
Willy Tarreau15a53a42015-01-21 13:39:42 +0100275 ret = pcre_exec(preg->reg, preg->extra, subject, length, 0, options, matches, enmatch * 3);
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200276 if (ret < 0)
277 return 0;
David Carlierf2592b22016-11-21 21:25:58 +0000278#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200279
280 if (ret == 0)
281 ret = enmatch;
282
283 for (i=0; i<nmatch; i++) {
284 /* Copy offset. */
285 if (i < ret) {
286 pmatch[i].rm_so = matches[(i*2)];
287 pmatch[i].rm_eo = matches[(i*2)+1];
288 continue;
289 }
290 /* Set the unmatvh flag (-1). */
291 pmatch[i].rm_so = -1;
292 pmatch[i].rm_eo = -1;
293 }
David Carlierf2592b22016-11-21 21:25:58 +0000294#ifdef USE_PCRE2
295 pcre2_match_data_free(pm);
296#endif
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200297 return 1;
298#else
299 char old_char = subject[length];
300 int match;
Willy Tarreau15a53a42015-01-21 13:39:42 +0100301
302 flags &= REG_NOTBOL;
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200303 subject[length] = 0;
Willy Tarreau15a53a42015-01-21 13:39:42 +0100304 match = regexec(&preg->regex, subject, nmatch, pmatch, flags);
Thierry FOURNIERb8f980c2014-06-11 13:59:05 +0200305 subject[length] = old_char;
306 if (match == REG_NOMATCH)
307 return 0;
308 return 1;
309#endif
310}
311
Dragan Dosen26743032019-04-30 15:54:36 +0200312struct my_regex *regex_comp(const char *str, int cs, int cap, char **err)
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200313{
Dragan Dosen26743032019-04-30 15:54:36 +0200314 struct my_regex *regex = NULL;
Thierry FOURNIER26202762014-06-18 11:50:51 +0200315#if defined(USE_PCRE) || defined(USE_PCRE_JIT)
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200316 int flags = 0;
317 const char *error;
318 int erroffset;
Dragan Dosen26743032019-04-30 15:54:36 +0200319#elif defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
320 int flags = 0;
321 int errn;
322#if defined(USE_PCRE2_JIT)
323 int jit;
324#endif
325 PCRE2_UCHAR error[256];
326 PCRE2_SIZE erroffset;
327#else
328 int flags = REG_EXTENDED;
329#endif
330
331 regex = calloc(1, sizeof(*regex));
332 if (!regex) {
333 memprintf(err, "not enough memory to build regex");
334 goto out_fail_alloc;
335 }
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200336
Dragan Dosen26743032019-04-30 15:54:36 +0200337#if defined(USE_PCRE) || defined(USE_PCRE_JIT)
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200338 if (!cs)
339 flags |= PCRE_CASELESS;
340 if (!cap)
341 flags |= PCRE_NO_AUTO_CAPTURE;
342
343 regex->reg = pcre_compile(str, flags, &error, &erroffset, NULL);
344 if (!regex->reg) {
345 memprintf(err, "regex '%s' is invalid (error=%s, erroffset=%d)", str, error, erroffset);
Dragan Dosen26743032019-04-30 15:54:36 +0200346 goto out_fail_alloc;
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200347 }
348
349 regex->extra = pcre_study(regex->reg, PCRE_STUDY_JIT_COMPILE, &error);
Christian Ruppert955f4612014-10-29 17:05:53 +0100350 if (!regex->extra && error != NULL) {
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200351 pcre_free(regex->reg);
352 memprintf(err, "failed to compile regex '%s' (error=%s)", str, error);
Dragan Dosen26743032019-04-30 15:54:36 +0200353 goto out_fail_alloc;
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200354 }
David Carlierf2592b22016-11-21 21:25:58 +0000355#elif defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
David Carlierf2592b22016-11-21 21:25:58 +0000356 if (!cs)
357 flags |= PCRE2_CASELESS;
358 if (!cap)
359 flags |= PCRE2_NO_AUTO_CAPTURE;
360
361 regex->reg = pcre2_compile((PCRE2_SPTR)str, PCRE2_ZERO_TERMINATED, flags, &errn, &erroffset, NULL);
362 if (!regex->reg) {
363 pcre2_get_error_message(errn, error, sizeof(error));
364 memprintf(err, "regex '%s' is invalid (error=%s, erroffset=%zu)", str, error, erroffset);
Dragan Dosen26743032019-04-30 15:54:36 +0200365 goto out_fail_alloc;
David Carlierf2592b22016-11-21 21:25:58 +0000366 }
367
David Carlier7adf8f32020-08-13 14:53:41 +0100368 regex->mfn = &pcre2_match;
David Carlierf2592b22016-11-21 21:25:58 +0000369#if defined(USE_PCRE2_JIT)
370 jit = pcre2_jit_compile(regex->reg, PCRE2_JIT_COMPLETE);
371 /*
372 * We end if it is an error not related to lack of JIT support
373 * in a case of JIT support missing pcre2_jit_compile is "no-op"
374 */
Christopher Faulet9e1f83d2022-09-01 19:34:00 +0200375 if (!jit)
David Carlier7adf8f32020-08-13 14:53:41 +0100376 regex->mfn = &pcre2_jit_match;
Christopher Faulet9e1f83d2022-09-01 19:34:00 +0200377 else {
378 if (jit != PCRE2_ERROR_JIT_BADOPTION) {
379 pcre2_code_free(regex->reg);
380 memprintf(err, "regex '%s' jit compilation failed", str);
381 goto out_fail_alloc;
382 }
383 else
384 regex->mfn = &pcre2_match;
David Carlierf2592b22016-11-21 21:25:58 +0000385 }
386#endif
387
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200388#else
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200389 if (!cs)
390 flags |= REG_ICASE;
391 if (!cap)
392 flags |= REG_NOSUB;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200393
Thierry FOURNIER799c0422013-12-06 20:36:20 +0100394 if (regcomp(&regex->regex, str, flags) != 0) {
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200395 memprintf(err, "regex '%s' is invalid", str);
Dragan Dosen26743032019-04-30 15:54:36 +0200396 goto out_fail_alloc;
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200397 }
398#endif
Dragan Dosen26743032019-04-30 15:54:36 +0200399 return regex;
400
401 out_fail_alloc:
402 free(regex);
403 return NULL;
Thierry FOURNIERed5a4ae2013-10-14 14:07:36 +0200404}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200405
Willy Tarreau80713382018-11-26 10:19:54 +0100406static void regex_register_build_options(void)
Willy Tarreau7a9ac6d2016-12-21 19:13:14 +0100407{
408 char *ptr = NULL;
409
410#ifdef USE_PCRE
411 memprintf(&ptr, "Built with PCRE version : %s", (HAP_XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
412 HAP_XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) :
413 HAP_XSTRING(PCRE_MAJOR.PCRE_MINOR) HAP_XSTRING(PCRE_PRERELEASE PCRE_DATE));
414 memprintf(&ptr, "%s\nRunning on PCRE version : %s", ptr, pcre_version());
415
416 memprintf(&ptr, "%s\nPCRE library supports JIT : %s", ptr,
417#ifdef USE_PCRE_JIT
418 ({
419 int r;
420 pcre_config(PCRE_CONFIG_JIT, &r);
421 r ? "yes" : "no (libpcre build without JIT?)";
422 })
423#else
424 "no (USE_PCRE_JIT not set)"
425#endif
426 );
David Carlierf2592b22016-11-21 21:25:58 +0000427#endif /* USE_PCRE */
428
429#ifdef USE_PCRE2
430 memprintf(&ptr, "Built with PCRE2 version : %s", (HAP_XSTRING(Z PCRE2_PRERELEASE)[1] == 0) ?
431 HAP_XSTRING(PCRE2_MAJOR.PCRE2_MINOR PCRE2_DATE) :
432 HAP_XSTRING(PCRE2_MAJOR.PCRE2_MINOR) HAP_XSTRING(PCRE2_PRERELEASE PCRE2_DATE));
433 memprintf(&ptr, "%s\nPCRE2 library supports JIT : %s", ptr,
434#ifdef USE_PCRE2_JIT
435 ({
436 int r;
437 pcre2_config(PCRE2_CONFIG_JIT, &r);
438 r ? "yes" : "no (libpcre2 build without JIT?)";
439 })
Willy Tarreau7a9ac6d2016-12-21 19:13:14 +0100440#else
David Carlierf2592b22016-11-21 21:25:58 +0000441 "no (USE_PCRE2_JIT not set)"
442#endif
443 );
444#endif /* USE_PCRE2 */
445
446#if !defined(USE_PCRE) && !defined(USE_PCRE2)
447 memprintf(&ptr, "Built without PCRE or PCRE2 support (using libc's regex instead)");
Willy Tarreau7a9ac6d2016-12-21 19:13:14 +0100448#endif
449 hap_register_build_opts(ptr, 1);
450}
451
Willy Tarreau80713382018-11-26 10:19:54 +0100452INITCALL0(STG_REGISTER, regex_register_build_options);
453
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454/*
455 * Local variables:
456 * c-indent-level: 8
457 * c-basic-offset: 8
458 * End:
459 */