pcre.c, etc.: Support the PCRE2 library.
[anag] / pcre.c
diff --git a/pcre.c b/pcre.c
index f15e37a..b30fc9b 100644 (file)
--- a/pcre.c
+++ b/pcre.c
 
 /*----- Header files ------------------------------------------------------*/
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
+#include "anag.h"
 
-#ifndef HAVE_PCRE
-  extern int dummy;
-#else
+#ifdef HAVE_PCRE2
+#  define PCRE2_CODE_UNIT_WIDTH 8
+#  include <pcre2.h>
+#endif
 
-#include "anag.h"
-#include <pcre.h>
+#ifdef HAVE_PCRE
+#  include <pcre.h>
+#endif
 
 /*----- Data structures ---------------------------------------------------*/
 
 typedef struct node_pcre {
   node n;
   const char *s;
+#ifdef HAVE_PCRE2
+  pcre2_code *rx;
+  pcre2_match_data *m;
+#endif
+#ifdef HAVE_PCRE
   pcre *rx;
   pcre_extra *rx_study;
   int *ovec;
   int ovecsz;
+#endif
 } node_pcre;
 
 /*----- Main code ---------------------------------------------------------*/
@@ -55,15 +61,30 @@ typedef struct node_pcre {
 static int n_pcre(node *nn, const char *p, size_t sz)
 {
   node_pcre *n = (node_pcre *)nn;
+#ifdef HAVE_PCRE2
+  char buf[128];
+  int rc;
+#endif
+#ifdef HAVE_PCRE
   int e;
+#endif
 
+#ifdef HAVE_PCRE2
+  rc = pcre2_match(n->rx, (PCRE2_SPTR)p, sz, 0, 0, n->m, 0);
+  if (rc >= 0) return (1);
+  else switch (rc) {
+    case PCRE2_ERROR_NOMATCH: return (0);
+    default:
+      rc = pcre2_get_error_message(rc, (PCRE2_UCHAR *)buf, sizeof(buf));
+      assert(!rc); die("pcre2 matching failed': %s", buf);
+  }
+#endif
+#ifdef HAVE_PCRE
   e = pcre_exec(n->rx, n->rx_study, p, sz, 0, 0, n->ovec, n->ovecsz);
-  if (e >= 0)
-    return (1);
-  if (e == PCRE_ERROR_NOMATCH)
-    return (0);
+  if (e >= 0) return (1);
+  if (e == PCRE_ERROR_NOMATCH) return (0);
   die("unexpected PCRE error code %d", e);
-  return (-1);
+#endif
 }
 
 /* --- Node creation --- */
@@ -71,22 +92,47 @@ static int n_pcre(node *nn, const char *p, size_t sz)
 node *pcrenode(const char *const *av)
 {
   node_pcre *n = xmalloc(sizeof(*n));
+#ifdef HAVE_PCRE2
+  char buf[128];
+  int err;
+  PCRE2_SIZE eo;
+  uint32_t c;
+#endif
+#ifdef HAVE_PCRE
   const char *e;
   int eo;
   int c;
+#endif
 
   n->n.func = n_pcre;
-  if ((n->rx = pcre_compile(av[0], PCRE_CASELESS, &e, &eo, 0)) == 0)
-    die("bad regular expression `%s': %s", av[0], e);
+
+#ifdef HAVE_PCRE2
+  n->rx = pcre2_compile((PCRE2_SPTR)av[0], strlen(av[0]), PCRE2_CASELESS,
+                       &err, &eo, 0);
+  if (!n->rx) {
+    err = pcre2_get_error_message(err, (PCRE2_UCHAR *)buf, sizeof(buf));
+    assert(!err); die("bad regular expression `%s': %s", av[0], buf);
+  }
+  err = pcre2_pattern_info(n->rx, PCRE2_INFO_BACKREFMAX, &c);
+  assert(!err);
+  n->m = pcre2_match_data_create_from_pattern(n->rx, 0);
+  if (!n->m) {
+    err = pcre2_get_error_message(err, (PCRE2_UCHAR *)buf, sizeof(buf));
+    assert(!err); die("failed to allocate match data: %s", buf);
+  }
+  pcre2_jit_compile(n->rx, PCRE2_JIT_COMPLETE);
+#endif
+#ifdef HAVE_PCRE
+  n->rx = pcre_compile(av[0], PCRE_CASELESS, &e, &eo, 0);
+  if (!n->rx) die("bad regular expression `%s': %s", av[0], e);
   n->rx_study = pcre_study(n->rx, 0, &e);
-  if (e)
-    die("error studying pattern `%s': %s", av[0], e);
-  pcre_fullinfo(n->rx, n->rx_study, PCRE_INFO_BACKREFMAX, &c);
-  n->ovecsz = c * 2;
-  n->ovec = xmalloc(n->ovecsz * sizeof(*n->ovec));
+  if (e) die("error studying pattern `%s': %s", av[0], e);
+  pcre_fullinfo(n->rx, n->rx_study, PCRE_INFO_CAPTURECOUNT, &c);
+  n->ovecsz = 2*c;
+  n->ovec = xmalloc(n->ovecsz*sizeof(*n->ovec));
+#endif
+
   return (&n->n);
 }
 
 /*----- That's all, folks -------------------------------------------------*/
-
-#endif