]> git.kaiwu.me - njs.git/commitdiff
Building regexp backend as an external.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 24 Dec 2021 15:48:11 +0000 (15:48 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 24 Dec 2021 15:48:11 +0000 (15:48 +0000)
This allows not to build PCRE specific code as a part of libnjs.a thus
supporting nginx builds with flags like --with-pcre=PCRE_DIR.  When
--no-pcre configure option is provided external code have to implement
methods declared in njs_regex.h.

This also closes #18 issue on Github.

auto/options
auto/pcre
auto/sources
auto/summary
external/njs_regex.c [moved from src/njs_pcre.c with 63% similarity]
nginx/config
nginx/config.make
nginx/ngx_js_regex.c [new file with mode: 0644]
src/njs_pcre2.c [deleted file]

index c4282280133cbccc44f78ffbbf3716ca0b04ae0a..5aab0845ee9e7be5914a906eac8899d85535f26c 100644 (file)
@@ -12,6 +12,8 @@ NJS_ADDRESS_SANITIZER=NO
 NJS_TEST262=YES
 
 NJS_OPENSSL=YES
+
+NJS_PCRE=YES
 NJS_TRY_PCRE2=YES
 
 NJS_CONFIGURE_OPTIONS=
@@ -35,6 +37,8 @@ do
         --test262=*)                     NJS_TEST262="$value"                ;;
 
         --no-openssl)                    NJS_OPENSSL=NO                      ;;
+
+        --no-pcre)                       NJS_PCRE=NO                         ;;
         --no-pcre2)                      NJS_TRY_PCRE2=NO                    ;;
 
         --help)
index e7e696b24041f5dd997051c9f4c0efa7d76b191c..8d51cf8c3359a7367da27fdd48f1988a31c0353d 100644 (file)
--- a/auto/pcre
+++ b/auto/pcre
@@ -2,72 +2,81 @@
 # Copyright (C) Igor Sysoev
 # Copyright (C) NGINX, Inc.
 
-njs_found=no
-NJS_HAVE_PCRE2=NO
+NJS_PCRE_CFLAGS=
+NJS_PCRE_LIB=
 
-if [ $NJS_TRY_PCRE2 = YES ]; then
-    if /bin/sh -c "(pcre2-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
+NJS_HAVE_PCRE=NO
 
-        NJS_PCRE_CFLAGS=`pcre2-config --cflags`
-        NJS_PCRE_LIB=`pcre2-config --libs8`
+if [ $NJS_PCRE = YES ]; then
 
-        njs_feature="PCRE2 library"
-        njs_feature_name=NJS_HAVE_PCRE2
-        njs_feature_run=no
-        njs_feature_incs="-DPCRE2_CODE_UNIT_WIDTH=8 $NJS_PCRE_CFLAGS"
-        njs_feature_libs=$NJS_PCRE_LIB
-        njs_feature_test="#include <pcre2.h>
+    njs_found=no
 
-                          int main(void) {
-                              pcre2_code  *re;
+    if [ $NJS_TRY_PCRE2 = YES ]; then
+        if /bin/sh -c "(pcre2-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
 
-                              re = pcre2_compile((PCRE2_SPTR)\"\",
-                                                 PCRE2_ZERO_TERMINATED, 0,
-                                                 NULL, NULL, NULL);
-                              return (re == NULL);
-                          }"
+            NJS_PCRE_CFLAGS=`pcre2-config --cflags`
+            NJS_PCRE_LIB=`pcre2-config --libs8`
 
-        . auto/feature
+            njs_feature="PCRE2 library"
+            njs_feature_name=NJS_HAVE_PCRE2
+            njs_feature_run=no
+            njs_feature_incs="-DPCRE2_CODE_UNIT_WIDTH=8 $NJS_PCRE_CFLAGS"
+            njs_feature_libs=$NJS_PCRE_LIB
+            njs_feature_test="#include <pcre2.h>
 
-        if [ $njs_found = yes ]; then
-            NJS_HAVE_PCRE2=YES
-            echo " + PCRE2 version: `pcre2-config --version`"
-        fi
-    fi
-fi
-
-if [ $njs_found = no ]; then
-    if /bin/sh -c "(pcre-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
-
-        NJS_PCRE_CFLAGS=`pcre-config --cflags`
-        NJS_PCRE_LIB=`pcre-config --libs`
+                              int main(void) {
+                                  pcre2_code  *re;
 
-        njs_feature="PCRE library"
-        njs_feature_name=NJS_HAVE_PCRE
-        njs_feature_run=no
-        njs_feature_incs=$NJS_PCRE_CFLAGS
-        njs_feature_libs=$NJS_PCRE_LIB
-        njs_feature_test="#include <pcre.h>
+                                  re = pcre2_compile((PCRE2_SPTR)\"\",
+                                                     PCRE2_ZERO_TERMINATED, 0,
+                                                     NULL, NULL, NULL);
+                                  return (re == NULL);
+                              }"
 
-                         int main(void) {
-                             pcre  *re;
+            . auto/feature
 
-                             re = pcre_compile(NULL, 0, NULL, 0, NULL);
-                             if (re == NULL)
-                                 return 1;
-                             return 0;
-                         }"
-        . auto/feature
+            if [ $njs_found = yes ]; then
+                NJS_HAVE_PCRE=YES
+                echo " + PCRE2 version: `pcre2-config --version`"
+            fi
+        fi
+    fi
 
-        if [ $njs_found = yes ]; then
-            echo " + PCRE version: `pcre-config --version`"
+    if [ $njs_found = no ]; then
+        if /bin/sh -c "(pcre-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
+
+            NJS_PCRE_CFLAGS=`pcre-config --cflags`
+            NJS_PCRE_LIB=`pcre-config --libs`
+
+            njs_feature="PCRE library"
+            njs_feature_name=NJS_HAVE_PCRE
+            njs_feature_run=no
+            njs_feature_incs=$NJS_PCRE_CFLAGS
+            njs_feature_libs=$NJS_PCRE_LIB
+            njs_feature_test="#include <pcre.h>
+
+                             int main(void) {
+                                 pcre  *re;
+
+                                 re = pcre_compile(NULL, 0, NULL, 0, NULL);
+                                 if (re == NULL)
+                                     return 1;
+                                 return 0;
+                             }"
+            . auto/feature
+
+            if [ $njs_found = yes ]; then
+                NJS_HAVE_PCRE=YES
+                echo " + PCRE version: `pcre-config --version`"
+            fi
         fi
     fi
-fi
 
-if [ $njs_found = no ]; then
-    echo
-    echo $0: error: no PCRE library found.
-    echo
-    exit 1;
+    if [ $njs_found = no ]; then
+        echo
+        echo $0: error: no PCRE library found.
+        echo
+        exit 1;
+    fi
+
 fi
index 21ca33451db90c52197c493ba9f72e242214b532..cdbda94c14acfb07fc60ee3298e066622abdbe85 100644 (file)
@@ -59,14 +59,6 @@ NJS_LIB_SRCS=" \
    src/njs_async.c \
 "
 
-NJS_LIB_PCRE_SRCS=" \
-   src/njs_pcre.c \
-"
-
-NJS_LIB_PCRE2_SRCS=" \
-   src/njs_pcre2.c \
-"
-
 NJS_LIB_TEST_SRCS=" \
    src/test/lvlhsh_unit_test.c \
    src/test/random_unit_test.c \
@@ -79,10 +71,8 @@ NJS_TEST_SRCS=" \
    src/test/njs_benchmark.c \
 "
 
-if [ "$NJS_HAVE_PCRE2" = "YES" ]; then
-       NJS_LIB_SRCS="$NJS_LIB_SRCS $NJS_LIB_PCRE2_SRCS"
-else
-       NJS_LIB_SRCS="$NJS_LIB_SRCS $NJS_LIB_PCRE_SRCS"
+if [ "$NJS_PCRE" = "YES" ]; then
+       NJS_LIB_SRCS="$NJS_LIB_SRCS external/njs_regex.c"
 fi
 
 NJS_TS_SRCS=$(find ts/ -name "*.d.ts" -o -name "*.json")
index 154d47c66eb3e73d4d75db4b2dc255c1b4a93507..8d17807bc108cbce52d410202e994233ac4d3872 100644 (file)
@@ -9,7 +9,10 @@ echo
 echo " + using CC: \"$CC\""
 echo " + using CFLAGS: \"$NJS_CFLAGS $NJS_CC_OPT $CFLAGS\""
 echo
-echo " + using PCRE library: $NJS_PCRE_LIB"
+
+if [ $NJS_HAVE_PCRE = YES ]; then
+  echo " + using PCRE library: $NJS_PCRE_LIB"
+fi
 
 if [ $NJS_HAVE_READLINE = YES ]; then
   echo " + using readline library: $NJS_READLINE_LIB"
similarity index 63%
rename from src/njs_pcre.c
rename to external/njs_regex.c
index c9e6e9ecce782adb5f598d6059f54dc22288e411..183e52e6efb9269c77b2b5361f9f829cd9425676 100644 (file)
@@ -1,12 +1,23 @@
 
 /*
  * Copyright (C) Igor Sysoev
+ * Copyright (C) Dmitry Volyntsev
  * Copyright (C) NGINX, Inc.
  */
 
 
 #include <njs_main.h>
 
+#ifdef NJS_HAVE_PCRE2
+
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+
+static const u_char* njs_regex_pcre2_error(int errcode, u_char buffer[128]);
+
+#else
+
 #include <pcre.h>
 
 
@@ -16,11 +27,19 @@ static void njs_pcre_free(void *p);
 
 static njs_regex_generic_ctx_t  *regex_context;
 
+#endif
+
 
 njs_regex_generic_ctx_t *
 njs_regex_generic_ctx_create(njs_pcre_malloc_t private_malloc,
     njs_pcre_free_t private_free, void *memory_data)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    return pcre2_general_context_create(private_malloc, private_free,
+                                        memory_data);
+#else
+
     njs_regex_generic_ctx_t  *ctx;
 
     ctx = private_malloc(sizeof(njs_regex_generic_ctx_t), memory_data);
@@ -32,29 +51,46 @@ njs_regex_generic_ctx_create(njs_pcre_malloc_t private_malloc,
     }
 
     return ctx;
+
+#endif
 }
 
 
 njs_regex_compile_ctx_t *
 njs_regex_compile_ctx_create(njs_regex_generic_ctx_t *ctx)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    return pcre2_compile_context_create(ctx);
+
+#else
+
     return ctx;
+
+#endif
 }
 
 
-/*
- * 1) PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with
- * lone closing square brackets as invalid.  Whereas according
- * to ES6: 11.8.5 it is a valid regexp expression.
- *
- * 2) escaping zero byte characters as "\u0000".
- *
- * Escaping it here as a workaround.
- */
 
 njs_int_t
 njs_regex_escape(njs_mp_t *mp, njs_str_t *text)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    return NJS_OK;
+
+#else
+
+    /*
+     * 1) PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with
+     * lone closing square brackets as invalid.  Whereas according
+     * to ES6: 11.8.5 it is a valid regexp expression.
+     *
+     * 2) escaping zero byte characters as "\u0000".
+     *
+     * Escaping it here as a workaround.
+     */
+
     size_t      brackets, zeros;
     u_char      *p, *dst, *start, *end;
     njs_bool_t  in;
@@ -151,6 +187,8 @@ done:
     text->length = dst - text->start;
 
     return NJS_OK;
+
+#endif
 }
 
 
@@ -158,6 +196,112 @@ njs_int_t
 njs_regex_compile(njs_regex_t *regex, u_char *source, size_t len,
     njs_regex_flags_t flags, njs_regex_compile_ctx_t *cctx, njs_trace_t *trace)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    int         ret;
+    u_char      *error;
+    size_t      erroff;
+    njs_uint_t  options;
+    u_char      errstr[128];
+
+    options = PCRE2_ALT_BSUX | PCRE2_MATCH_UNSET_BACKREF;
+
+    if ((flags & NJS_REGEX_IGNORE_CASE)) {
+         options |= PCRE2_CASELESS;
+    }
+
+    if ((flags & NJS_REGEX_MULTILINE)) {
+         options |= PCRE2_MULTILINE;
+    }
+
+    if ((flags & NJS_REGEX_STICKY)) {
+         options |= PCRE2_ANCHORED;
+    }
+
+    if ((flags & NJS_REGEX_UTF8)) {
+         options |= PCRE2_UTF;
+    }
+
+    regex->code = pcre2_compile(source, len, options, &ret, &erroff, cctx);
+
+    if (njs_slow_path(regex->code == NULL)) {
+        error = &source[erroff];
+
+        njs_alert(trace, NJS_LEVEL_ERROR,
+                  "pcre_compile2(\"%s\") failed: %s at \"%s\"",
+                  source, njs_regex_pcre2_error(ret, errstr), error);
+
+        return NJS_DECLINED;
+    }
+
+    ret = pcre2_pattern_info(regex->code, PCRE2_INFO_CAPTURECOUNT,
+                             &regex->ncaptures);
+
+    if (njs_slow_path(ret < 0)) {
+        njs_alert(trace, NJS_LEVEL_ERROR,
+               "pcre2_pattern_info(\"%s\", PCRE2_INFO_CAPTURECOUNT) failed: %s",
+               source, njs_regex_pcre2_error(ret, errstr));
+
+        return NJS_ERROR;
+    }
+
+    ret = pcre2_pattern_info(regex->code, PCRE2_INFO_BACKREFMAX,
+                             &regex->backrefmax);
+
+    if (njs_slow_path(ret < 0)) {
+        njs_alert(trace, NJS_LEVEL_ERROR,
+                 "pcre2_pattern_info(\"%s\", PCRE2_INFO_BACKREFMAX) failed: %s",
+                 source, njs_regex_pcre2_error(ret, errstr));
+
+        return NJS_ERROR;
+    }
+
+    /* Reserve additional elements for the first "$0" capture. */
+    regex->ncaptures++;
+
+    if (regex->ncaptures > 1) {
+        ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMECOUNT,
+                                 &regex->nentries);
+
+        if (njs_slow_path(ret < 0)) {
+            njs_alert(trace, NJS_LEVEL_ERROR,
+                  "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMECOUNT) failed: %s",
+                   source, njs_regex_pcre2_error(ret, errstr));
+
+            return NJS_ERROR;
+        }
+
+        if (regex->nentries != 0) {
+            ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMEENTRYSIZE,
+                                     &regex->entry_size);
+
+            if (njs_slow_path(ret < 0)) {
+                njs_alert(trace, NJS_LEVEL_ERROR,
+                          "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMEENTRYSIZE)"
+                          " failed: %s", source,
+                          njs_regex_pcre2_error(ret, errstr));
+
+                return NJS_ERROR;
+            }
+
+            ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMETABLE,
+                                     &regex->entries);
+
+            if (njs_slow_path(ret < 0)) {
+                njs_alert(trace, NJS_LEVEL_ERROR,
+                          "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMETABLE) "
+                          "failed: %s", source,
+                          njs_regex_pcre2_error(ret, errstr));
+
+                return NJS_ERROR;
+            }
+        }
+    }
+
+    return NJS_OK;
+
+#else
+
     int                      ret, err, erroff;
     char                     *pattern, *error;
     void                     *(*saved_malloc)(size_t size);
@@ -297,6 +441,8 @@ done:
     regex_context = NULL;
 
     return ret;
+
+#endif
 }
 
 
@@ -332,6 +478,16 @@ njs_regex_named_captures(njs_regex_t *regex, njs_str_t *name, int n)
 njs_regex_match_data_t *
 njs_regex_match_data(njs_regex_t *regex, njs_regex_generic_ctx_t *ctx)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    if (regex != NULL) {
+        return pcre2_match_data_create_from_pattern(regex->code, ctx);
+    }
+
+    return pcre2_match_data_create(0, ctx);
+
+#else
+
     size_t                  size;
     njs_uint_t              ncaptures;
     njs_regex_match_data_t  *match_data;
@@ -354,6 +510,8 @@ njs_regex_match_data(njs_regex_t *regex, njs_regex_generic_ctx_t *ctx)
     }
 
     return match_data;
+
+#endif
 }
 
 
@@ -361,21 +519,15 @@ void
 njs_regex_match_data_free(njs_regex_match_data_t *match_data,
     njs_regex_generic_ctx_t *ctx)
 {
-    ctx->private_free(match_data, ctx->memory_data);
-}
+#ifdef NJS_HAVE_PCRE2
 
+    pcre2_match_data_free(match_data);
 
-static void *
-njs_pcre_malloc(size_t size)
-{
-    return regex_context->private_malloc(size, regex_context->memory_data);
-}
+#else
 
+    ctx->private_free(match_data, ctx->memory_data);
 
-static void
-njs_pcre_free(void *p)
-{
-    regex_context->private_free(p, regex_context->memory_data);
+#endif
 }
 
 
@@ -383,6 +535,27 @@ njs_int_t
 njs_regex_match(njs_regex_t *regex, const u_char *subject, size_t off,
     size_t len, njs_regex_match_data_t *match_data, njs_trace_t *trace)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    int     ret;
+    u_char  errstr[128];
+
+    ret = pcre2_match(regex->code, subject, len, off, 0, match_data, NULL);
+
+    if (ret < 0) {
+        if (ret == PCRE2_ERROR_NOMATCH) {
+            return NJS_DECLINED;
+        }
+
+        njs_alert(trace, NJS_LEVEL_ERROR, "pcre2_match() failed: %s",
+                  njs_regex_pcre2_error(ret, errstr));
+        return NJS_ERROR;
+    }
+
+    return ret;
+
+#else
+
     int  ret;
 
     ret = pcre_exec(regex->code, regex->extra, (const char *) subject, len,
@@ -398,11 +571,58 @@ njs_regex_match(njs_regex_t *regex, const u_char *subject, size_t off,
     }
 
     return ret;
+
+#endif
 }
 
 
 size_t
 njs_regex_capture(njs_regex_match_data_t *match_data, njs_uint_t n)
 {
+#ifdef NJS_HAVE_PCRE2
+
+    size_t  c;
+
+    c = pcre2_get_ovector_pointer(match_data)[n];
+
+    if (c == PCRE2_UNSET) {
+        return NJS_REGEX_UNSET;
+    }
+
+    return c;
+
+#else
+
     return match_data->captures[n];
+
+#endif
+}
+
+#ifdef NJS_HAVE_PCRE2
+
+static const u_char *
+njs_regex_pcre2_error(int errcode, u_char buffer[128])
+{
+    pcre2_get_error_message(errcode, buffer, 128);
+
+    return buffer;
+}
+
+#else
+
+static void *
+njs_pcre_malloc(size_t size)
+{
+    return regex_context->private_malloc(size, regex_context->memory_data);
+}
+
+
+static void
+njs_pcre_free(void *p)
+{
+    regex_context->private_free(p, regex_context->memory_data);
 }
+
+#endif
+
+
index 3b4de1029ce49295ec621168ed9950214507c3ca..1cc3c4360f56bbeb650db46b03784fd4ad09d58d 100644 (file)
@@ -4,6 +4,7 @@ NJS_DEPS="$ngx_addon_dir/ngx_js.h \
     $ngx_addon_dir/ngx_js_fetch.h"
 NJS_SRCS="$ngx_addon_dir/ngx_js.c \
     $ngx_addon_dir/ngx_js_fetch.c \
+    $ngx_addon_dir/ngx_js_regex.c \
     $ngx_addon_dir/../external/njs_webcrypto_module.c"
 
 if [ $HTTP != NO ]; then
index 7210c0da621c7e044e601e294e50a2e2573e3421..64e435159663a6aaee5983b98e2c0865570b6120 100644 (file)
@@ -3,7 +3,7 @@ cat << END                                            >> $NGX_MAKEFILE
 $ngx_addon_dir/../build/libnjs.a: $NGX_MAKEFILE
        cd $ngx_addon_dir/.. \\
        && if [ -f build/Makefile ]; then \$(MAKE) clean; fi \\
-       && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl --no-pcre2 \\
-       && \$(MAKE)
+       && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl --no-pcre \\
+       && \$(MAKE) libnjs
 
 END
diff --git a/nginx/ngx_js_regex.c b/nginx/ngx_js_regex.c
new file mode 100644 (file)
index 0000000..b88316e
--- /dev/null
@@ -0,0 +1,16 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) NGINX, Inc.
+ */
+
+
+#include <ngx_config.h>
+
+#if (NGX_PCRE2)
+
+#define NJS_HAVE_PCRE2  1
+
+#endif
+
+#include "../external/njs_regex.c"
diff --git a/src/njs_pcre2.c b/src/njs_pcre2.c
deleted file mode 100644 (file)
index 1cebc45..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-
-/*
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
- */
-
-
-#include <njs_main.h>
-
-#define PCRE2_CODE_UNIT_WIDTH 8
-#include <pcre2.h>
-
-
-static const u_char* njs_regex_pcre2_error(int errcode, u_char buffer[128]);
-
-
-njs_regex_generic_ctx_t *
-njs_regex_generic_ctx_create(njs_pcre_malloc_t private_malloc,
-    njs_pcre_free_t private_free, void *memory_data)
-{
-    return pcre2_general_context_create(private_malloc, private_free,
-                                        memory_data);
-}
-
-
-njs_regex_compile_ctx_t *
-njs_regex_compile_ctx_create(njs_regex_generic_ctx_t *ctx)
-{
-    return pcre2_compile_context_create(ctx);
-}
-
-
-njs_int_t
-njs_regex_escape(njs_mp_t *mp, njs_str_t *text)
-{
-    return NJS_OK;
-}
-
-
-njs_int_t
-njs_regex_compile(njs_regex_t *regex, u_char *source, size_t len,
-    njs_regex_flags_t flags, njs_regex_compile_ctx_t *ctx, njs_trace_t *trace)
-{
-    int         ret;
-    u_char      *error;
-    size_t      erroff;
-    njs_uint_t  options;
-    u_char      errstr[128];
-
-    options = PCRE2_ALT_BSUX | PCRE2_MATCH_UNSET_BACKREF;
-
-    if ((flags & NJS_REGEX_IGNORE_CASE)) {
-         options |= PCRE2_CASELESS;
-    }
-
-    if ((flags & NJS_REGEX_MULTILINE)) {
-         options |= PCRE2_MULTILINE;
-    }
-
-    if ((flags & NJS_REGEX_STICKY)) {
-         options |= PCRE2_ANCHORED;
-    }
-
-    if ((flags & NJS_REGEX_UTF8)) {
-         options |= PCRE2_UTF;
-    }
-
-    regex->code = pcre2_compile(source, len, options, &ret, &erroff, ctx);
-
-    if (njs_slow_path(regex->code == NULL)) {
-        error = &source[erroff];
-
-        njs_alert(trace, NJS_LEVEL_ERROR,
-                  "pcre_compile2(\"%s\") failed: %s at \"%s\"",
-                  source, njs_regex_pcre2_error(ret, errstr), error);
-
-        return NJS_DECLINED;
-    }
-
-    ret = pcre2_pattern_info(regex->code, PCRE2_INFO_CAPTURECOUNT,
-                             &regex->ncaptures);
-
-    if (njs_slow_path(ret < 0)) {
-        njs_alert(trace, NJS_LEVEL_ERROR,
-               "pcre2_pattern_info(\"%s\", PCRE2_INFO_CAPTURECOUNT) failed: %s",
-               source, njs_regex_pcre2_error(ret, errstr));
-
-        return NJS_ERROR;
-    }
-
-    ret = pcre2_pattern_info(regex->code, PCRE2_INFO_BACKREFMAX,
-                             &regex->backrefmax);
-
-    if (njs_slow_path(ret < 0)) {
-        njs_alert(trace, NJS_LEVEL_ERROR,
-                 "pcre2_pattern_info(\"%s\", PCRE2_INFO_BACKREFMAX) failed: %s",
-                 source, njs_regex_pcre2_error(ret, errstr));
-
-        return NJS_ERROR;
-    }
-
-    /* Reserve additional elements for the first "$0" capture. */
-    regex->ncaptures++;
-
-    if (regex->ncaptures > 1) {
-        ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMECOUNT,
-                                 &regex->nentries);
-
-        if (njs_slow_path(ret < 0)) {
-            njs_alert(trace, NJS_LEVEL_ERROR,
-                  "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMECOUNT) failed: %s",
-                   source, njs_regex_pcre2_error(ret, errstr));
-
-            return NJS_ERROR;
-        }
-
-        if (regex->nentries != 0) {
-            ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMEENTRYSIZE,
-                                     &regex->entry_size);
-
-            if (njs_slow_path(ret < 0)) {
-                njs_alert(trace, NJS_LEVEL_ERROR,
-                          "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMEENTRYSIZE)"
-                          " failed: %s", source,
-                          njs_regex_pcre2_error(ret, errstr));
-
-                return NJS_ERROR;
-            }
-
-            ret = pcre2_pattern_info(regex->code, PCRE2_INFO_NAMETABLE,
-                                     &regex->entries);
-
-            if (njs_slow_path(ret < 0)) {
-                njs_alert(trace, NJS_LEVEL_ERROR,
-                          "pcre2_pattern_info(\"%s\", PCRE2_INFO_NAMETABLE) "
-                          "failed: %s", source,
-                          njs_regex_pcre2_error(ret, errstr));
-
-                return NJS_ERROR;
-            }
-        }
-    }
-
-    return NJS_OK;
-}
-
-
-njs_bool_t
-njs_regex_is_valid(njs_regex_t *regex)
-{
-    return (regex->code != NULL);
-}
-
-
-njs_int_t
-njs_regex_named_captures(njs_regex_t *regex, njs_str_t *name, int n)
-{
-    char  *entry;
-
-    if (name == NULL) {
-        return regex->nentries;
-    }
-
-    if (n >= regex->nentries) {
-        return NJS_ERROR;
-    }
-
-    entry = regex->entries + regex->entry_size * n;
-
-    name->start = (u_char *) entry + 2;
-    name->length = njs_strlen(name->start);
-
-    return (entry[0] << 8) + entry[1];
-}
-
-
-njs_regex_match_data_t *
-njs_regex_match_data(njs_regex_t *regex, njs_regex_generic_ctx_t *ctx)
-{
-    if (regex != NULL) {
-        return pcre2_match_data_create_from_pattern(regex->code, ctx);
-    }
-
-    return pcre2_match_data_create(0, ctx);
-}
-
-
-void
-njs_regex_match_data_free(njs_regex_match_data_t *match_data,
-    njs_regex_generic_ctx_t *unused)
-{
-    pcre2_match_data_free(match_data);
-}
-
-
-njs_int_t
-njs_regex_match(njs_regex_t *regex, const u_char *subject, size_t off,
-    size_t len, njs_regex_match_data_t *match_data, njs_trace_t *trace)
-{
-    int     ret;
-    u_char  errstr[128];
-
-    ret = pcre2_match(regex->code, subject, len, off, 0, match_data, NULL);
-
-    if (ret < 0) {
-        if (ret == PCRE2_ERROR_NOMATCH) {
-            return NJS_DECLINED;
-        }
-
-        njs_alert(trace, NJS_LEVEL_ERROR, "pcre2_match() failed: %s",
-                  njs_regex_pcre2_error(ret, errstr));
-        return NJS_ERROR;
-    }
-
-    return ret;
-}
-
-
-size_t
-njs_regex_capture(njs_regex_match_data_t *match_data, njs_uint_t n)
-{
-    size_t  c;
-
-    c = pcre2_get_ovector_pointer(match_data)[n];
-
-    if (c == PCRE2_UNSET) {
-        return NJS_REGEX_UNSET;
-    }
-
-    return c;
-}
-
-
-static const u_char *
-njs_regex_pcre2_error(int errcode, u_char buffer[128])
-{
-    pcre2_get_error_message(errcode, buffer, 128);
-
-    return buffer;
-}