diff --git a/pkgs/by-name/ld/ldmud/package.nix b/pkgs/by-name/ld/ldmud/package.nix index e93f77462a5d..554efc4eb9ee 100644 --- a/pkgs/by-name/ld/ldmud/package.nix +++ b/pkgs/by-name/ld/ldmud/package.nix @@ -6,7 +6,7 @@ pkg-config, bison, libiconv, - pcre, + pcre2, libgcrypt, libxcrypt-legacy, json_c, @@ -39,6 +39,11 @@ stdenv.mkDerivation (finalAttrs: { patches = [ ./mysql-compat.patch + # pcre2 support, vendored from the upstream maintainer's release prep + # branch, which is rebased regularly and so unsuitable for fetchpatch: + # https://github.com/amotzkau/ldmud/commit/421ae90e611b3a4816bf52d84abfdcc73bf999b7 + # Remove when updating to the next release. + ./pcre2.patch ]; sourceRoot = "${finalAttrs.src.name}/src"; @@ -52,7 +57,7 @@ stdenv.mkDerivation (finalAttrs: { buildInputs = [ libgcrypt libxcrypt-legacy - pcre + pcre2 json_c libxml2 ] diff --git a/pkgs/by-name/ld/ldmud/pcre2.patch b/pkgs/by-name/ld/ldmud/pcre2.patch new file mode 100644 index 000000000000..587d51cb0b5e --- /dev/null +++ b/pkgs/by-name/ld/ldmud/pcre2.patch @@ -0,0 +1,620 @@ +From 421ae90e611b3a4816bf52d84abfdcc73bf999b7 Mon Sep 17 00:00:00 2001 +From: Alexander Motzkau +Date: Tue, 9 Sep 2025 23:15:11 +0200 +Subject: [PATCH] Implement support for libpcre2 + +The original libpcre library is deprecated and not supported anymore. +Therefore use libpcre2 instead if available. +--- + src/autoconf/configure.ac | 10 +- + src/driver.h | 2 +- + src/lex.c | 2 +- + src/mregex.c | 335 ++++++++++++++++++++++++++++++++++---- + src/pkg-pcre.h | 11 +- + src/simulate.c | 2 +- + 6 files changed, 327 insertions(+), 35 deletions(-) + +diff --git src/autoconf/configure.ac src/autoconf/configure.ac +index e04bcc659..678c2f487 100644 +--- src/autoconf/configure.ac ++++ src/autoconf/configure.ac +@@ -1301,7 +1301,15 @@ int main(void) + else + lp_cv_has_pcre=no + fi +-if test "$lp_cv_has_pcre" = "no" && test "x$enable_use_pcre" = "xyes"; then ++ ++lp_cv_has_pcre2_lib="no" ++AC_CHECK_LIB(pcre2-8, pcre2_config_8, PKGLIBS="$PKGLIBS -lpcre2-8" lp_cv_has_pcre2_lib="yes") ++ ++if test "$lp_cv_has_pcre2_lib" = "yes"; then ++ AC_DEFINE(HAS_PCRE2, 1, [Does the machine offer PCRE2?]) ++fi ++ ++if test "$lp_cv_has_pcre" = "no" && test "$lp_cv_has_pcre2_lib" = "no" && test "x$enable_use_pcre" = "xyes"; then + AC_NOT_AVAILABLE(use-pcre) + fi + +diff --git src/driver.h src/driver.h +index ec10645ac..00509f59b 100644 +--- src/driver.h ++++ src/driver.h +@@ -139,7 +139,7 @@ + + /* If USE_PCRE is defined, check if the libpcre is available on this system. + * Disable USE_PCRE if not. */ +-#if defined(USE_PCRE) && !defined(HAS_PCRE) ++#if defined(USE_PCRE) && !defined(HAS_PCRE) && !defined(HAS_PCRE2) + #undef USE_PCRE + #endif + +diff --git src/lex.c src/lex.c +index df61f4435..783428515 100644 +--- src/lex.c ++++ src/lex.c +@@ -920,7 +920,7 @@ init_lexer(void) + #ifdef USE_JSON + add_permanent_define_str("__JSON__", -1, "1"); + #endif +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE) || defined(HAS_PCRE2) + add_permanent_define_str("__PCRE__", -1, "1"); + #endif + add_permanent_define_str("__LPC_NOSAVE__", -1, "1"); +diff --git src/mregex.c src/mregex.c +index 17014ddde..81b6ef826 100644 +--- src/mregex.c ++++ src/mregex.c +@@ -80,18 +80,22 @@ + */ + + typedef struct regdata_s { +- p_uint ref; /* Number of refs */ +- int opt; /* Additional options, but no package flags */ ++ p_uint ref; /* Number of refs */ ++ int opt; /* Additional options, but no package flags */ + /* -- PCRE -- */ +-#ifdef HAS_PCRE +- pcre * pProg; /* The generated regular expression */ +- pcre_extra * pHints; /* Study data */ +- int num_subs; /* Number of elements in pSubs */ +- int * pSubs; /* Substring offsets + workarea */ +- int res; /* Result of last rx_exec() */ ++#if defined(HAS_PCRE2) ++ pcre2_code * pcre_prog; /* The compiled regular expression */ ++ pcre2_match_data * pcre_match_data; /* Block for holding the result */ ++ int res; /* Result of last pcre2_match() */ ++#elif defined(HAS_PCRE) ++ pcre * pProg; /* The generated regular expression */ ++ pcre_extra * pHints; /* Study data */ ++ int num_subs; /* Number of elements in pSubs */ ++ int * pSubs; /* Substring offsets + workarea */ ++ int res; /* Result of last rx_exec() */ + #endif // HAS_PCRE + /* -- Traditional -- */ +- regexp * rx; /* The actual regular expression */ ++ regexp * rx; /* The actual regular expression */ + } regdata_t; + + #ifdef RXCACHE_TABLE +@@ -143,7 +147,14 @@ static uint32 iXSizeAlloc = 0; /* Dynamic memory held in regexp structs */ + + #endif /* RXCACHE_TABLE */ + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++static bool in_init_context = false; ++static pcre2_general_context* general_context = NULL; ++static pcre2_compile_context* compile_context = NULL; ++static pcre2_match_context* match_context = NULL; ++#endif ++ ++#if defined(HAS_PCRE) || defined(HAS_PCRE2) + static size_t pcre_malloc_size; + /* Accumulated size from pcre_malloc() calls. Used when creating + * a new PCRE to capture its allocated size for statistics. +@@ -197,7 +208,41 @@ free_regdata(regdata_t *r) + #endif /* RXCHACHE_TABLE */ + + /*--------------------------------------------------------------------*/ +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++static void * ++pcre_xalloc (PCRE2_SIZE size, void *data) ++ ++/* Wrapper function so that PCRE will use our special allocator. */ ++ ++{ ++ void * p; ++ ++ if (!pcre_malloc_err) ++ pcre_malloc_err = "in PCRE function"; ++ if (in_init_context) ++ { ++ p = pxalloc(size); ++ if (p == NULL) ++ fatal("Out of memory (%zu bytes) for pcre context\n", (size_t)(size)); ++ } ++ else ++ xallocate(p, size, pcre_malloc_err); ++ pcre_malloc_size += size; ++ return p; ++} /* pcre_xalloc() */ ++ ++/*--------------------------------------------------------------------*/ ++static void ++pcre_xfree (void *block, void *data) ++ ++/* Wrapper function so that PCRE will use our special allocator. */ ++ ++{ ++ xfree(block); ++} /* pcre_xalloc() */ ++ ++/*--------------------------------------------------------------------*/ ++#elif defined(HAS_PCRE) + static void * + pcre_xalloc (size_t size) + +@@ -223,7 +268,9 @@ rx_pcre_version (void) + + { + static char buf[40]; +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ snprintf(buf, sizeof(buf), "%d.%d", PCRE2_MAJOR, PCRE2_MINOR); ++#elif defined(HAS_PCRE) + snprintf(buf, sizeof(buf), "%d.%d", PCRE_MAJOR, PCRE_MINOR); + #else + sprintf(buf, "not available"); +@@ -240,7 +287,22 @@ void rx_init(void) + #ifdef RXCACHE_TABLE + memset(xtable, 0, sizeof(xtable)); + #endif +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ in_init_context = true; ++ general_context = pcre2_general_context_create(pcre_xalloc, pcre_xfree, NULL); ++ compile_context = pcre2_compile_context_create(general_context); ++ match_context = pcre2_match_context_create(general_context); ++ in_init_context = false; ++ ++#if LD_PCRE_RECURSION_LIMIT > 0 ++ pcre2_set_depth_limit(match_context, LD_PCRE_RECURSION_LIMIT); ++#endif ++ ++ uint32_t opt = 0; ++ if (pcre2_config(PCRE2_CONFIG_UNICODE, &opt) || !opt) ++ fprintf(stderr, "%s PCRE2 package does not support Unicode.\n", time_stamp()); ++ ++#elif defined(HAS_PCRE) + int opt = 0; + + pcre_malloc = pcre_xalloc; +@@ -259,10 +321,22 @@ get_error_message (int code, int package) + /* Return a constant string with the error message for + * generated by . + * If is not an error, NULL is returned. ++ * Subsequent calls to this function may overwrite previous results. + */ + + { +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (package & RE_PCRE) ++ { ++ static unsigned char buf[256]; ++ ++ if (!code) ++ return NULL; ++ if (pcre2_get_error_message(code, buf, sizeof(buf)) == PCRE2_ERROR_BADDATA) ++ return "unknown error"; ++ return (const char*) buf; ++ } ++#elif defined(HAS_PCRE) + if (package & RE_PCRE) + { + const char* text; +@@ -373,7 +447,70 @@ rx_compile_re (string_t * expr, int opt, Bool from_ed, regdata_t * rdata) + } /* rx_compile_re() */ + + /*--------------------------------------------------------------------*/ +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++static size_t ++rx_compile_pcre (string_t * expr, int opt, Bool from_ed, regdata_t * rdata) ++ ++/* Compile the expression with the options into a PCRE2 ++ * expression and store it into *. ++ * On success, return the accumulated size of the expression. ++ * On failure, if is FALSE, an error is thrown. ++ * On failure, if is TRUE, the error message is printed directly ++ * to the user and the function returns with 0. ++ */ ++ ++{ ++ uint32_t pcre_opt; /* translated into PCRE opts */ ++ int err_code; ++ PCRE2_SIZE err_offset; ++ pcre2_code* pcre_prog; ++ pcre2_match_data* pcre_match_data; ++ ++ /* Sanitize the value */ ++ opt = opt & ~(RE_EXCOMPATIBLE) & ~(RE_PACKAGE_MASK); ++ ++ /* Determine the RE compilation options */ ++ pcre_opt = PCRE2_UTF | PCRE2_UCP; ++ if (opt & RE_CASELESS) pcre_opt |= PCRE2_CASELESS; ++ if (opt & RE_MULTILINE) pcre_opt |= PCRE2_MULTILINE; ++ if (opt & RE_DOTALL) pcre_opt |= PCRE2_DOTALL; ++ if (opt & RE_EXTENDED) pcre_opt |= PCRE2_EXTENDED; ++ if (opt & RE_DOLLAR_ENDONLY) pcre_opt |= PCRE2_DOLLAR_ENDONLY; ++ if (opt & RE_UNGREEDY) pcre_opt |= PCRE2_UNGREEDY; ++ ++ /* Compile the RE */ ++ pcre_malloc_size = 0; ++ pcre_malloc_err = "compiling regex"; ++ pcre_prog = pcre2_compile((unsigned char*) get_txt(expr), mstrsize(expr), ++ pcre_opt, &err_code, &err_offset, compile_context); ++ ++ if (pcre_prog == NULL) ++ { ++ rx_free_subdata(rdata); /* Might have HS data in it already */ ++ if (from_ed) ++ add_message("pcre: %s at offset %d\n", get_error_message(err_code, RE_PCRE), (int)err_offset); ++ else ++ errorf("pcre: %s at offset %d\n", get_error_message(err_code, RE_PCRE), (int)err_offset); ++ return 0; ++ } ++ ++ pcre_malloc_err = "JIT compiling regex"; ++ pcre2_jit_compile(pcre_prog, PCRE2_JIT_COMPLETE); ++ ++ pcre_match_data = pcre2_match_data_create_from_pattern(pcre_prog, general_context); ++ ++ /* Compilation complete - store the result in the outgoing regdata ++ * structure. ++ */ ++ ++ rdata->pcre_prog = pcre_prog; ++ rdata->pcre_match_data = pcre_match_data; ++ rdata->res = 0; ++ ++ return pcre_malloc_size; ++} /* rx_compile_pcre() */ ++/*--------------------------------------------------------------------*/ ++#elif defined(HAS_PCRE) + static size_t + rx_compile_pcre (string_t * expr, int opt, Bool from_ed, regdata_t * rdata) + +@@ -537,8 +674,12 @@ rx_compile_data (string_t * expr, int opt, Bool from_ed) + + /* Regexp found, but it may not have been compiled for us yet. + */ +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) || defined(HAS_PCRE) ++#if defined(HAS_PCRE2) ++ if ((opt & RE_PCRE) && !pHash->base.pcre_prog) ++#else + if ((opt & RE_PCRE) && !pHash->base.pProg) ++#endif + { + pHash->size = rx_compile_pcre(expr, opt, from_ed, &(pHash->base)); + if (!pHash->size) +@@ -560,7 +701,7 @@ rx_compile_data (string_t * expr, int opt, Bool from_ed) + pcre_size = 0; + memset(&rdata, 0, sizeof(rdata)); + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE) || defined(HAS_PCRE2) + if (opt & RE_PCRE) + { + pcre_size = rx_compile_pcre(expr, opt, from_ed, &rdata); +@@ -673,7 +814,7 @@ rx_compile (string_t * expr, int opt, Bool from_ed) + errorf("Missing specification of which regexp package to use.\n"); + return NULL; + } +-#ifndef HAS_PCRE ++#if !(defined(HAS_PCRE) || defined(HAS_PCRE2)) + if (opt & RE_PCRE) + { + if (from_ed) +@@ -716,7 +857,31 @@ rx_exec (regexp_t *pRegexp, string_t * string, size_t start) + { + regdata_t * prog = pRegexp->data; + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ uint32_t pcre_opt = 0; ++ ++ /* Determine the RE compilation options */ ++ if (prog->opt & RE_ANCHORED) pcre_opt |= PCRE2_ANCHORED; ++ if (prog->opt & RE_NOTBOL) pcre_opt |= PCRE2_NOTBOL; ++ if (prog->opt & RE_NOTEOL) pcre_opt |= PCRE2_NOTEOL; ++ if (prog->opt & RE_NOTEMPTY) pcre_opt |= PCRE2_NOTEMPTY; ++ ++ prog->res = pcre2_match(prog->pcre_prog, (unsigned char*)get_txt(string), mstrsize(string), ++ start, pcre_opt, prog->pcre_match_data, match_context); ++ ++ /* Reverse the roles of return codes 0 (pcre_match_data too small) ++ * and PCRE_ERROR_NOMATCH. ++ */ ++ if (prog->res == PCRE2_ERROR_NOMATCH) ++ prog->res = 0; ++ else if (prog->res == 0) ++ prog->res = PCRE2_ERROR_NOMATCH; ++ ++ return prog->res; ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + int rc; +@@ -776,7 +941,32 @@ rx_exec_str (regexp_t *pRegexp, char * string, char * start) + + { + regdata_t * prog = pRegexp->data; +-#ifdef HAS_PCRE ++ ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ uint32_t pcre_opt = 0; ++ ++ /* Determine the RE compilation options */ ++ if (prog->opt & RE_ANCHORED) pcre_opt |= PCRE2_ANCHORED; ++ if (prog->opt & RE_NOTBOL) pcre_opt |= PCRE2_NOTBOL; ++ if (prog->opt & RE_NOTEOL) pcre_opt |= PCRE2_NOTEOL; ++ if (prog->opt & RE_NOTEMPTY) pcre_opt |= PCRE2_NOTEMPTY; ++ ++ prog->res = pcre2_match(prog->pcre_prog, (unsigned char*)start, PCRE2_ZERO_TERMINATED, ++ string - start, pcre_opt, prog->pcre_match_data, match_context); ++ ++ /* Reverse the roles of return codes 0 (pcre_match_data too small) ++ * and PCRE_ERROR_NOMATCH. ++ */ ++ if (prog->res == PCRE2_ERROR_NOMATCH) ++ prog->res = 0; ++ else if (prog->res == 0) ++ prog->res = PCRE2_ERROR_NOMATCH; ++ ++ return prog->res; ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + int rc; +@@ -835,7 +1025,7 @@ rx_num_matches (regexp_t *pRegexp) + */ + + { +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) || defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + return pRegexp->data->res >= 1 ? pRegexp->data->res : 0; +@@ -881,7 +1071,25 @@ rx_get_match_n (regexp_t *pRegexp, string_t * str, int n, size_t * start, size_t + Bool rc; + regdata_t * prog = pRegexp->data; + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ PCRE2_SIZE* subs = pcre2_get_ovector_pointer(prog->pcre_match_data); ++ if (n < 0 || n >= prog->res || subs[2*n] == PCRE2_UNSET || subs[2*n+1] == PCRE2_UNSET) ++ { ++ *start = 0; ++ *end = 0; ++ rc = false; ++ } ++ else ++ { ++ *start = (size_t) subs[2*n]; ++ *end = (size_t) subs[2*n+1]; ++ rc = true; ++ } ++ return rc; ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + if (n < 0 +@@ -937,7 +1145,16 @@ rx_get_match (regexp_t *pRegexp, string_t * str, size_t * start, size_t * end) + { + regdata_t * prog = pRegexp->data; + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ PCRE2_SIZE* subs = pcre2_get_ovector_pointer(prog->pcre_match_data); ++ ++ *start = (size_t) subs[0]; ++ *end = (size_t) subs[1]; ++ return; ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + *start = (size_t)prog->pSubs[0]; +@@ -963,7 +1180,16 @@ rx_get_match_str (regexp_t *pRegexp, char * str, size_t * start, size_t * end) + { + regdata_t * prog = pRegexp->data; + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ PCRE2_SIZE* subs = pcre2_get_ovector_pointer(prog->pcre_match_data); ++ ++ *start = (size_t) subs[0]; ++ *end = (size_t) subs[1]; ++ return; ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + *start = (size_t)prog->pSubs[0]; +@@ -1042,7 +1268,28 @@ rx_sub (regexp_t *pRegexp, string_t *source, string_t *subst) + } + else + { +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (pRegexp->opt & RE_PCRE) ++ { ++ PCRE2_SIZE* subs = pcre2_get_ovector_pointer(prog->pcre_match_data); ++ ++ if (no < prog->res && subs[2*no] != PCRE2_UNSET && subs[2*no+1] != PCRE2_UNSET) ++ { ++ size_t start = (size_t) subs[2*no]; ++ size_t sublen = (size_t) subs[2*no+1] - start; ++ ++ if (copyPass) ++ { ++ memcpy(dst, get_txt(source)+start, sublen); ++ dst += sublen; ++ } ++ else ++ { ++ len += sublen; ++ } ++ } ++ } ++#elif defined(HAS_PCRE) + if (pRegexp->opt & RE_PCRE) + { + if (no < prog->res +@@ -1139,7 +1386,7 @@ rx_sub_str (regexp_t *pRegexp, char *source, char *subst) + /*-------------------------------------------------------------------------*/ + Bool + rx_reganch (regexp_t *pRegexp) +- ++ + /* If is a traditional regexp, return TRUE if rx->reganch + * is not NULL. If is a PCRE, always return FALSE. + * +@@ -1162,7 +1409,19 @@ rx_free_subdata (regdata_t * expr) + */ + + { +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++ if (expr->pcre_match_data) ++ { ++ pcre2_match_data_free(expr->pcre_match_data); ++ expr->pcre_match_data = NULL; ++ } ++ ++ if (expr->pcre_prog) ++ { ++ pcre2_code_free(expr->pcre_prog); ++ expr->pcre_prog = NULL; ++ } ++#elif defined(HAS_PCRE) + if (expr->pSubs) + { + xfree(expr->pSubs); +@@ -1324,6 +1583,20 @@ rxcache_driver_info (svalue_t *svp, int value) + /*--------------------------------------------------------------------*/ + #if defined(GC_SUPPORT) + ++/*--------------------------------------------------------------------*/ ++void ++clear_regdata_ref (regdata_t * pRegexp) ++ ++/* Clear regexp data where we cannot follow references. ++ */ ++ ++{ ++#if defined(HAS_PCRE2) ++ if (pRegexp->pcre_prog != NULL) ++ rx_free_subdata(pRegexp); ++#endif ++} /* clear_regdata_ref() */ ++ + /*--------------------------------------------------------------------*/ + void + clear_rxcache_refs (void) +@@ -1341,6 +1614,7 @@ clear_rxcache_refs (void) + if (NULL != xtable[i]) + { + xtable[i]->base.ref = 0; ++ clear_regdata_ref(&xtable[i]->base); + } + #endif + } /* clear_rxcache_refs() */ +@@ -1354,7 +1628,10 @@ clear_regexp_ref (regexp_t * pRegexp) + + { + if (pRegexp) ++ { + pRegexp->data->ref = 0; ++ clear_regdata_ref(pRegexp->data); ++ } + } /* clear_regexp_ref() */ + + /*--------------------------------------------------------------------*/ +@@ -1368,7 +1645,7 @@ count_regdata_ref (regdata_t * pRegexp) + + { + note_malloced_block_ref(pRegexp); +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE) + if (pRegexp->pProg) + { + note_malloced_block_ref(pRegexp->pProg); +@@ -1414,7 +1691,7 @@ count_rxcache_refs (void) + { + if (NULL != xtable[i]) + { +- count_regdata_ref((regdata_t *)xtable[i]); ++ count_regdata_ref(&xtable[i]->base); + } + } /* for (i) */ + #endif +diff --git src/pkg-pcre.h src/pkg-pcre.h +index 7aa622561..21e452916 100644 +--- src/pkg-pcre.h ++++ src/pkg-pcre.h +@@ -11,9 +11,15 @@ + + #include "driver.h" + +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE2) ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include ++ ++#define RE_ERROR_BACKTRACK (-8) // Free error code, see regexp.h for others. ++#undef HAS_PCRE ++ ++#elif defined(HAS_PCRE) + #include +-#endif + + /* Error code to be returned if too many backtracks are detected. + */ +@@ -22,5 +28,6 @@ + #else + #define RE_ERROR_BACKTRACK (-8) // PCRE_ERROR_MATCHLIMIT from PCRE + #endif ++#endif + + #endif /* PKG_PCRE_H_ */ +diff --git src/simulate.c src/simulate.c +index ac29fed98..6c4c73783 100644 +--- src/simulate.c ++++ src/simulate.c +@@ -5108,7 +5108,7 @@ f_set_driver_hook (svalue_t *sp) + } + else if (n == H_REGEXP_PACKAGE) + { +-#ifdef HAS_PCRE ++#if defined(HAS_PCRE) || defined(HAS_PCRE2) + if (sp->u.number != RE_PCRE + && sp->u.number != RE_TRADITIONAL ) + {