<pre style='margin:0'>
Perry E. Metzger (pmetzger) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/daccb0f68f57cb36d00223bfb29fb41eb4b4830f">https://github.com/macports/macports-ports/commit/daccb0f68f57cb36d00223bfb29fb41eb4b4830f</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new daccb0f68f5 sqlite3-pcre2: new port with SQLite regex extension
</span>daccb0f68f5 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit daccb0f68f57cb36d00223bfb29fb41eb4b4830f
</span>Author: nilason <n_larsson@yahoo.com>
AuthorDate: Wed Jun 14 12:22:12 2023 +0200

<span style='display:block; white-space:pre;color:#404040;'>    sqlite3-pcre2: new port with SQLite regex extension
</span>---
 databases/sqlite3-pcre2/Portfile           |  52 ++++++
 databases/sqlite3-pcre2/files/prec2_c.diff | 251 +++++++++++++++++++++++++++++
 databases/sqlite3-pcre2/files/test.sh      |  10 ++
 3 files changed, 313 insertions(+)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/databases/sqlite3-pcre2/Portfile b/databases/sqlite3-pcre2/Portfile
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..7de08ba7b48
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/databases/sqlite3-pcre2/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,52 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+PortSystem          1.0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+name                sqlite3-pcre2
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+version             0.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+revision            0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+categories          databases
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+license             public-domain
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+maintainers         {yahoo.com:n_larsson @nilason} openmaintainer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+description         Perl-compatible regular expression support for SQLite
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+long_description    {*}${description}.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+homepage            https://git.altlinux.org/people/at/packages/?p=sqlite3-pcre.git
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+patchfiles-append   prec2_c.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fetch.type          git
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+git.url             git://git.altlinux.org/people/at/packages/sqlite3-pcre.git
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+git.branch          4229ecc
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+depends_build       port:pkgconfig
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+depends_lib         port:sqlite3 \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    port:pcre2
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+use_configure       no
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+build {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set cflags [exec ${prefix}/bin/pkg-config --cflags sqlite3 libpcre2-8]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set libs [exec ${prefix}/bin/pkg-config --libs sqlite3 libpcre2-8]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    system -W ${worksrcpath} "${configure.cc} -fPIC -dynamiclib \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        -o pcre2.dylib ${cflags}  ${libs} \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        -current_version ${version} -compatibility_version ${version} pcre.c"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+destroot {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    file mkdir ${destroot}${prefix}/lib/sqlite3
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    file copy ${worksrcpath}/pcre2.dylib \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ${destroot}${prefix}/lib/sqlite3/pcre2.dylib
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test.cmd            ${filespath}/test.sh ${prefix} ${worksrcpath}/pcre2.dylib
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test.run            yes
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+notes-append \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+"Load the installed SQLite extension with\
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+'.load ${prefix}/lib/sqlite3/pcre2.dylib'."
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/databases/sqlite3-pcre2/files/prec2_c.diff b/databases/sqlite3-pcre2/files/prec2_c.diff
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..6d4ae8daa3a
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/databases/sqlite3-pcre2/files/prec2_c.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,251 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Patch made with:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+https://github.com/christian-proust/sqlite3-pcre2/blob/e3e02a4af39d5dfdbd2cc8801696ed9ae2faf569/pcre2.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+with the additional change to 'const unsigned char *pattern_str, *subject_str;'.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- pcre.c.orig    2023-06-14 08:44:05.000000000 +0200
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ pcre.c 2023-06-14 09:01:48.000000000 +0200
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1,22 +1,24 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Written by Alexey Tourbin <at@altlinux.org>.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * Initially written by Alexey Tourbin <at@altlinux.org>.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  * The author has dedicated the code to the public domain.  Anyone is free
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  * to copy, modify, publish, use, compile, sell, or distribute the original
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  * code, either in source code form or as a compiled binary, for any purpose,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  * commercial or non-commercial, and by any means.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define PCRE2_CODE_UNIT_WIDTH 8
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <assert.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <string.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <pcre.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <pcre2.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <sqlite3ext.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SQLITE_EXTENSION_INIT1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ typedef struct {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    char *s;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    pcre *p;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    pcre_extra *e;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    char *pattern_str;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    int pattern_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    pcre2_code *pattern_code;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } cache_entry;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #ifndef CACHE_SIZE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -24,96 +26,136 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    const char *re, *str;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    pcre *p;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    pcre_extra *e;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    const unsigned char *pattern_str, *subject_str;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    int pattern_len, subject_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    pcre2_code *pattern_code;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     assert(argc == 2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    /* check null */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    re = (const char *) sqlite3_value_text(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    if (!re) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  sqlite3_result_error(ctx, "no regexp", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    pattern_str = sqlite3_value_text(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (!pattern_str) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        sqlite3_result_error(ctx, "no pattern", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    pattern_len = sqlite3_value_bytes(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    str = (const char *) sqlite3_value_text(argv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    if (!str) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  sqlite3_result_error(ctx, "no string", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    subject_str = sqlite3_value_text(argv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (!subject_str) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        sqlite3_result_error(ctx, "no subject", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    subject_len = sqlite3_value_bytes(argv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     /* simple LRU cache */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  int i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  int found = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  cache_entry *cache = sqlite3_user_data(ctx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  assert(cache);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (strcmp(re, cache[i].s) == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          found = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (found) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (i > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          cache_entry c = cache[i];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          memmove(cache + 1, cache, i * sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          cache[0] = c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      cache_entry c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      const char *err;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      int pos;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      c.p = pcre_compile(re, 0, &err, &pos, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (!c.p) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          sqlite3_result_error(ctx, e2, -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          sqlite3_free(e2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      c.e = pcre_study(c.p, 0, &err);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      c.s = strdup(re);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (!c.s) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          sqlite3_result_error(ctx, "strdup: ENOMEM", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          pcre_free(c.p);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          pcre_free(c.e);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      i = CACHE_SIZE - 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (cache[i].s) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          free(cache[i].s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          assert(cache[i].p);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          pcre_free(cache[i].p);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-          pcre_free(cache[i].e);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      memmove(cache + 1, cache, i * sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      cache[0] = c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  p = cache[0].p;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  e = cache[0].e;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        int i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        int found = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        cache_entry *cache = sqlite3_user_data(ctx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        assert(cache);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        for (i = 0; i < CACHE_SIZE && cache[i].pattern_str; i++)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            if (
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pattern_len == cache[i].pattern_len
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                && memcmp(pattern_str, cache[i].pattern_str, pattern_len) == 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            ) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                found = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (found) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            if (i > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                cache_entry c = cache[i];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                memmove(cache + 1, cache, i * sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                cache[0] = c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            cache_entry c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            const char *err;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            int error_code;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            PCRE2_SIZE error_position;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            c.pattern_code = pcre2_compile(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pattern_str,           /* the pattern */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pattern_len,           /* the length of the pattern */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                0,                     /* default options */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                &error_code,           /* for error number */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                &error_position,       /* for error offset */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                NULL);                 /* use default compile context */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            if (!c.pattern_code) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                PCRE2_UCHAR error_buffer[256];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pcre2_get_error_message(error_code, error_buffer, sizeof(error_buffer));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                char *e2 = sqlite3_mprintf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    "Cannot compile pattern \"%s\" at offset %d: %s",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                    pattern_str, (int)error_position, error_buffer);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                sqlite3_result_error(ctx, e2, -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                sqlite3_free(e2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            c.pattern_str = malloc(pattern_len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            if (!c.pattern_str) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                sqlite3_result_error(ctx, "malloc: ENOMEM", -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pcre2_code_free(c.pattern_code);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            memcpy(c.pattern_str, pattern_str, pattern_len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            c.pattern_len = pattern_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            i = CACHE_SIZE - 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            if (cache[i].pattern_str) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                free(cache[i].pattern_str);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                assert(cache[i].pattern_code);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++                pcre2_code_free(cache[i].pattern_code);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            memmove(cache + 1, cache, i * sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            cache[0] = c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        pattern_code = cache[0].pattern_code;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  int rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  assert(p);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  sqlite3_result_int(ctx, rc >= 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        int rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        pcre2_match_data *match_data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        assert(pattern_code);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        match_data = pcre2_match_data_create_from_pattern(pattern_code, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        rc = pcre2_match(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          pattern_code,         /* the compiled pattern */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          subject_str,          /* the subject string */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          subject_len,          /* the length of the subject */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          0,                    /* start at offset 0 in the subject */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          0,                    /* default options */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          match_data,           /* block for storing the result */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          NULL);                /* use default match context */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        assert(rc != 0);  // because we have not set match_data
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if(rc >= 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          // Normal case because we have not set match_data
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          sqlite3_result_int(ctx, 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        } else if(rc == PCRE2_ERROR_NOMATCH) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          sqlite3_result_int(ctx, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        } else { // (rc < 0 and the code is not one of the above)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            PCRE2_UCHAR error_buffer[256];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            pcre2_get_error_message(rc, error_buffer, sizeof(error_buffer));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            char *e2 = sqlite3_mprintf("%s", error_buffer);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            sqlite3_result_error(ctx, e2, -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            sqlite3_free(e2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++            return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        pcre2_match_data_free(match_data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  SQLITE_EXTENSION_INIT2(api)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (!cache) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      *err = "calloc: ENOMEM";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    SQLITE_EXTENSION_INIT2(api)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (!cache) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        *err = "calloc: ENOMEM";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/databases/sqlite3-pcre2/files/test.sh b/databases/sqlite3-pcre2/files/test.sh
</span>new file mode 100755
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..a404e50cf31
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/databases/sqlite3-pcre2/files/test.sh
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,10 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#!/bin/sh
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+prefix="${1}"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+dylib="${2}"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+"${prefix}/bin/sqlite3" >out <<EOF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+.load ${dylib}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+SELECT "asdf" REGEXP "(?i)^A";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+EOF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+grep 1 out
</span></pre><pre style='margin:0'>

</pre>