[njs] Building regexp backend as an external.
Dmitry Volyntsev
xeioex at nginx.com
Fri Dec 24 16:58:43 UTC 2021
details: https://hg.nginx.org/njs/rev/8ef86212d24b
branches:
changeset: 1784:8ef86212d24b
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Dec 24 15:48:11 2021 +0000
description:
Building regexp backend as an external.
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.
diffstat:
auto/options | 4 +
auto/pcre | 113 ++++----
auto/sources | 14 +-
auto/summary | 5 +-
external/njs_regex.c | 628 +++++++++++++++++++++++++++++++++++++++++++++++++++
nginx/config | 1 +
nginx/config.make | 4 +-
nginx/ngx_js_regex.c | 16 +
src/njs_pcre.c | 408 ---------------------------------
src/njs_pcre2.c | 240 -------------------
10 files changed, 718 insertions(+), 715 deletions(-)
diffs (truncated from 1536 to 1000 lines):
diff -r c72703d60d43 -r 8ef86212d24b auto/options
--- a/auto/options Fri Dec 24 15:48:09 2021 +0000
+++ b/auto/options Fri Dec 24 15:48:11 2021 +0000
@@ -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)
diff -r c72703d60d43 -r 8ef86212d24b auto/pcre
--- a/auto/pcre Fri Dec 24 15:48:09 2021 +0000
+++ b/auto/pcre Fri Dec 24 15:48:11 2021 +0000
@@ -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=
+
+NJS_HAVE_PCRE=NO
+
+if [ $NJS_PCRE = YES ]; then
-if [ $NJS_TRY_PCRE2 = YES ]; then
- if /bin/sh -c "(pcre2-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
+ njs_found=no
- NJS_PCRE_CFLAGS=`pcre2-config --cflags`
- NJS_PCRE_LIB=`pcre2-config --libs8`
+ if [ $NJS_TRY_PCRE2 = YES ]; then
+ if /bin/sh -c "(pcre2-config --version)" >> $NJS_AUTOCONF_ERR 2>&1; then
+
+ NJS_PCRE_CFLAGS=`pcre2-config --cflags`
+ NJS_PCRE_LIB=`pcre2-config --libs8`
- 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_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>
- int main(void) {
- pcre2_code *re;
+ int main(void) {
+ pcre2_code *re;
- re = pcre2_compile((PCRE2_SPTR)\"\",
- PCRE2_ZERO_TERMINATED, 0,
- NULL, NULL, NULL);
- return (re == NULL);
- }"
+ re = pcre2_compile((PCRE2_SPTR)\"\",
+ PCRE2_ZERO_TERMINATED, 0,
+ NULL, NULL, NULL);
+ return (re == NULL);
+ }"
- . auto/feature
+ . auto/feature
- if [ $njs_found = yes ]; then
- NJS_HAVE_PCRE2=YES
- echo " + PCRE2 version: `pcre2-config --version`"
+ if [ $njs_found = yes ]; then
+ NJS_HAVE_PCRE=YES
+ echo " + PCRE2 version: `pcre2-config --version`"
+ fi
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`
-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>
- 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;
+ int main(void) {
+ pcre *re;
- re = pcre_compile(NULL, 0, NULL, 0, NULL);
- if (re == NULL)
- return 1;
- return 0;
- }"
- . auto/feature
+ re = pcre_compile(NULL, 0, NULL, 0, NULL);
+ if (re == NULL)
+ return 1;
+ return 0;
+ }"
+ . auto/feature
- if [ $njs_found = yes ]; then
- echo " + PCRE version: `pcre-config --version`"
+ 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
diff -r c72703d60d43 -r 8ef86212d24b auto/sources
--- a/auto/sources Fri Dec 24 15:48:09 2021 +0000
+++ b/auto/sources Fri Dec 24 15:48:11 2021 +0000
@@ -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")
diff -r c72703d60d43 -r 8ef86212d24b auto/summary
--- a/auto/summary Fri Dec 24 15:48:09 2021 +0000
+++ b/auto/summary Fri Dec 24 15:48:11 2021 +0000
@@ -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"
diff -r c72703d60d43 -r 8ef86212d24b external/njs_regex.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/njs_regex.c Fri Dec 24 15:48:11 2021 +0000
@@ -0,0 +1,628 @@
+
+/*
+ * 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>
+
+
+static void *njs_pcre_malloc(size_t size);
+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);
+
+ if (njs_fast_path(ctx != NULL)) {
+ ctx->private_malloc = private_malloc;
+ ctx->private_free = private_free;
+ ctx->memory_data = memory_data;
+ }
+
+ 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
+}
+
+
+
+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;
+
+ start = text->start;
+ end = text->start + text->length;
+
+ in = 0;
+ zeros = 0;
+ brackets = 0;
+
+ for (p = start; p < end; p++) {
+
+ switch (*p) {
+ case '[':
+ in = 1;
+ break;
+
+ case ']':
+ if (!in) {
+ brackets++;
+ }
+
+ in = 0;
+ break;
+
+ case '\\':
+ p++;
+
+ if (p == end || *p != '\0') {
+ break;
+ }
+
+ /* Fall through. */
+
+ case '\0':
+ zeros++;
+ break;
+ }
+ }
+
+ if (!brackets && !zeros) {
+ return NJS_OK;
+ }
+
+ text->length = text->length + brackets + zeros * njs_length("\\u0000");
+
+ text->start = njs_mp_alloc(mp, text->length);
+ if (njs_slow_path(text->start == NULL)) {
+ return NJS_ERROR;
+ }
+
+ in = 0;
+ dst = text->start;
+
+ for (p = start; p < end; p++) {
+
+ switch (*p) {
+ case '[':
+ in = 1;
+ break;
+
+ case ']':
+ if (!in) {
+ *dst++ = '\\';
+ }
+
+ in = 0;
+ break;
+
+ case '\\':
+ *dst++ = *p++;
+
+ if (p == end) {
+ goto done;
+ }
+
+ if (*p != '\0') {
+ break;
+ }
+
+ /* Fall through. */
+
+ case '\0':
+ dst = njs_cpymem(dst, "\\u0000", 6);
+ continue;
+ }
+
+ *dst++ = *p;
+ }
+
+done:
+
+ text->length = dst - text->start;
+
+ return NJS_OK;
+
+#endif
+}
+
+
+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,
+ ®ex->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,
+ ®ex->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,
+ ®ex->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,
+ ®ex->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,
+ ®ex->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);
+ void (*saved_free)(void *p);
+ njs_uint_t options;
+ const char *errstr;
+ njs_regex_generic_ctx_t *ctx;
+
+ ctx = cctx;
+
+ ret = NJS_ERROR;
+
+ saved_malloc = pcre_malloc;
+ pcre_malloc = njs_pcre_malloc;
+ saved_free = pcre_free;
+ pcre_free = njs_pcre_free;
+ regex_context = ctx;
+
+#ifdef PCRE_JAVASCRIPT_COMPAT
+ /* JavaScript compatibility has been introduced in PCRE-7.7. */
+ options = PCRE_JAVASCRIPT_COMPAT;
+#else
+ options = 0;
+#endif
+
+ if ((flags & NJS_REGEX_IGNORE_CASE)) {
+ options |= PCRE_CASELESS;
+ }
+
+ if ((flags & NJS_REGEX_MULTILINE)) {
+ options |= PCRE_MULTILINE;
+ }
+
+ if ((flags & NJS_REGEX_STICKY)) {
+ options |= PCRE_ANCHORED;
+ }
+
+ if ((flags & NJS_REGEX_UTF8)) {
+ options |= PCRE_UTF8;
+ }
+
+ pattern = (char *) source;
+
+ regex->code = pcre_compile(pattern, options, &errstr, &erroff, NULL);
+
+ if (njs_slow_path(regex->code == NULL)) {
+ error = pattern + erroff;
+
+ if (*error != '\0') {
+ njs_alert(trace, NJS_LEVEL_ERROR,
+ "pcre_compile(\"%s\") failed: %s at \"%s\"",
+ pattern, errstr, error);
+
+ } else {
+ njs_alert(trace, NJS_LEVEL_ERROR,
+ "pcre_compile(\"%s\") failed: %s", pattern, errstr);
+ }
+
+ ret = NJS_DECLINED;
+
+ goto done;
+ }
+
+ regex->extra = pcre_study(regex->code, 0, &errstr);
+
+ if (njs_slow_path(errstr != NULL)) {
+ njs_alert(trace, NJS_LEVEL_WARN,
+ "pcre_study(\"%s\") failed: %s", pattern, errstr);
+ }
+
+ err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_CAPTURECOUNT,
+ ®ex->ncaptures);
+
+ if (njs_slow_path(err < 0)) {
+ njs_alert(trace, NJS_LEVEL_ERROR,
+ "pcre_fullinfo(\"%s\", PCRE_INFO_CAPTURECOUNT) failed: %d",
+ pattern, err);
+
+ goto done;
+ }
+
+ err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_BACKREFMAX,
+ ®ex->backrefmax);
+
+ if (njs_slow_path(err < 0)) {
+ njs_alert(trace, NJS_LEVEL_ERROR,
+ "pcre_fullinfo(\"%s\", PCRE_INFO_BACKREFMAX) failed: %d",
+ pattern, err);
+
+ goto done;
+ }
+
+ /* Reserve additional elements for the first "$0" capture. */
+ regex->ncaptures++;
+
+ if (regex->ncaptures > 1) {
+ err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMECOUNT,
+ ®ex->nentries);
+
+ if (njs_slow_path(err < 0)) {
+ njs_alert(trace, NJS_LEVEL_ERROR,
+ "pcre_fullinfo(\"%s\", PCRE_INFO_NAMECOUNT) failed: %d",
+ pattern, err);
+
+ goto done;
+ }
+
+ if (regex->nentries != 0) {
+ err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMEENTRYSIZE,
+ ®ex->entry_size);
+
+ if (njs_slow_path(err < 0)) {
+ njs_alert(trace, NJS_LEVEL_ERROR, "pcre_fullinfo(\"%s\", "
+ "PCRE_INFO_NAMEENTRYSIZE) failed: %d", pattern, err);
+
+ goto done;
+ }
+
+ err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_NAMETABLE,
+ ®ex->entries);
+
+ if (njs_slow_path(err < 0)) {
+ njs_alert(trace, NJS_LEVEL_ERROR, "pcre_fullinfo(\"%s\", "
+ "PCRE_INFO_NAMETABLE) failed: %d", pattern, err);
+
+ goto done;
+ }
+ }
+ }
+
+ ret = NJS_OK;
+
+done:
+
+ pcre_malloc = saved_malloc;
+ pcre_free = saved_free;
+ regex_context = NULL;
+
+ return ret;
+
+#endif
+}
+
+
+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)
+{
+#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;
+
+ if (regex != NULL) {
+ ncaptures = regex->ncaptures - 1;
+
+ } else {
+ ncaptures = 0;
+ }
+
+ /* Each capture is stored in 3 "int" vector elements. */
+ ncaptures *= 3;
+ size = sizeof(njs_regex_match_data_t) + ncaptures * sizeof(int);
+
+ match_data = ctx->private_malloc(size, ctx->memory_data);
+
+ if (njs_fast_path(match_data != NULL)) {
+ match_data->ncaptures = ncaptures + 3;
+ }
+
+ return match_data;
+
+#endif
+}
+
+
+void
+njs_regex_match_data_free(njs_regex_match_data_t *match_data,
+ njs_regex_generic_ctx_t *ctx)
+{
+#ifdef NJS_HAVE_PCRE2
+
+ pcre2_match_data_free(match_data);
+
+#else
+
+ ctx->private_free(match_data, ctx->memory_data);
+
+#endif
+}
+
+
+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,
+ off, 0, match_data->captures, match_data->ncaptures);
+
+ if (ret <= PCRE_ERROR_NOMATCH) {
+ if (ret == PCRE_ERROR_NOMATCH) {
+ return NJS_DECLINED;
+ }
+
+ njs_alert(trace, NJS_LEVEL_ERROR, "pcre_exec() failed: %d", ret);
+ return NJS_ERROR;
+ }
+
+ 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
+
+
diff -r c72703d60d43 -r 8ef86212d24b nginx/config
--- a/nginx/config Fri Dec 24 15:48:09 2021 +0000
+++ b/nginx/config Fri Dec 24 15:48:11 2021 +0000
@@ -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
diff -r c72703d60d43 -r 8ef86212d24b nginx/config.make
--- a/nginx/config.make Fri Dec 24 15:48:09 2021 +0000
+++ b/nginx/config.make Fri Dec 24 15:48:11 2021 +0000
@@ -3,7 +3,7 @@ cat << END
$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 -r c72703d60d43 -r 8ef86212d24b nginx/ngx_js_regex.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nginx/ngx_js_regex.c Fri Dec 24 15:48:11 2021 +0000
@@ -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 -r c72703d60d43 -r 8ef86212d24b src/njs_pcre.c
--- a/src/njs_pcre.c Fri Dec 24 15:48:09 2021 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,408 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-
-#include <njs_main.h>
-
-#include <pcre.h>
-
-
-static void *njs_pcre_malloc(size_t size);
-static void njs_pcre_free(void *p);
-
-
-static njs_regex_generic_ctx_t *regex_context;
-
-
-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)
-{
- njs_regex_generic_ctx_t *ctx;
-
- ctx = private_malloc(sizeof(njs_regex_generic_ctx_t), memory_data);
-
- if (njs_fast_path(ctx != NULL)) {
- ctx->private_malloc = private_malloc;
- ctx->private_free = private_free;
- ctx->memory_data = memory_data;
- }
-
- return ctx;
-}
-
-
-njs_regex_compile_ctx_t *
-njs_regex_compile_ctx_create(njs_regex_generic_ctx_t *ctx)
-{
- return ctx;
-}
-
-
-/*
- * 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)
-{
- size_t brackets, zeros;
- u_char *p, *dst, *start, *end;
- njs_bool_t in;
-
- start = text->start;
- end = text->start + text->length;
-
- in = 0;
- zeros = 0;
- brackets = 0;
-
- for (p = start; p < end; p++) {
-
- switch (*p) {
- case '[':
- in = 1;
- break;
-
- case ']':
- if (!in) {
- brackets++;
- }
-
- in = 0;
- break;
-
- case '\\':
- p++;
-
- if (p == end || *p != '\0') {
- break;
- }
-
- /* Fall through. */
-
- case '\0':
- zeros++;
- break;
- }
- }
-
- if (!brackets && !zeros) {
- return NJS_OK;
- }
-
- text->length = text->length + brackets + zeros * njs_length("\\u0000");
-
- text->start = njs_mp_alloc(mp, text->length);
- if (njs_slow_path(text->start == NULL)) {
- return NJS_ERROR;
- }
-
- in = 0;
- dst = text->start;
-
- for (p = start; p < end; p++) {
-
- switch (*p) {
- case '[':
More information about the nginx-devel
mailing list