#if HAVE_UNISTD_H
# include <unistd.h>
#endif
-#include <pcre.h>
#include <ctype.h>
#if HAVE_GCRYPT_H
# include <gcrypt.h>
mem_init();
network_init();
/* garbage-collect PCRE's memory */
- pcre_malloc = xmalloc;
- pcre_free = xfree;
+ regexp_setup();
if(!setlocale(LC_CTYPE, "")) disorder_fatal(errno, "error calling setlocale");
if(!setlocale(LC_TIME, "")) disorder_fatal(errno, "error calling setlocale");
while((n = getopt_long(argc, argv, "+hVc:dHlNu:p:", options, 0)) >= 0) {
*/
#include "disobedience.h"
+#include "regexp.h"
#include "version.h"
#include <getopt.h>
#include <locale.h>
-#include <pcre.h>
#include <gcrypt.h>
/* Apologies for the numerous de-consting casts, but GLib et al do not seem to
mem_init();
/* garbage-collect PCRE's memory */
- pcre_malloc = xmalloc;
- pcre_free = xfree;
+ regexp_setup();
if(!setlocale(LC_CTYPE, "")) disorder_fatal(errno, "error calling setlocale");
gtkok = gtk_init_check(&argc, &argv);
while((n = getopt_long(argc, argv, "hVc:dtHC", options, 0)) >= 0) {
asprintf.c fprintf.c snprintf.c \
queue.c queue.h \
random.c random.h \
+ regexp.c regexp.h \
regsub.c regsub.h \
resample.c resample.h \
rights.c queue-rights.c rights.h \
#if HAVE_LANGINFO_H
# include <langinfo.h>
#endif
-#include <pcre.h>
+
#if HAVE_SHLOBJ_H
# include <Shlobj.h>
#endif
#include "charset.h"
#include "defs.h"
#include "printf.h"
+#include "regexp.h"
#include "regsub.h"
#include "signame.h"
#include "authhash.h"
int nvec, char **vec) {
struct namepartlist *npl = ADDRESS(cs->config, struct namepartlist);
unsigned reflags;
- const char *errstr;
- int erroffset, n;
- pcre *re;
+ regexp *re;
+ char errstr[RXCERR_LEN];
+ size_t erroffset;
+ int n;
if(nvec < 3) {
disorder_error(0, "%s:%d: namepart needs at least 3 arguments",
return -1;
}
reflags = nvec >= 5 ? regsub_flags(vec[4]) : 0;
- if(!(re = pcre_compile(vec[1],
- PCRE_UTF8
- |regsub_compile_options(reflags),
- &errstr, &erroffset, 0))) {
- disorder_error(0, "%s:%d: compiling regexp /%s/: %s (offset %d)",
+ if(!(re = regexp_compile(vec[1], regsub_compile_options(reflags),
+ errstr, sizeof(errstr), &erroffset)))
+ {
+ disorder_error(0, "%s:%d: compiling regexp /%s/: %s (offset %zu)",
cs->path, cs->line, vec[1], errstr, erroffset);
return -1;
}
const struct conf *whoami,
int nvec, char **vec) {
struct transformlist *tl = ADDRESS(cs->config, struct transformlist);
- pcre *re;
+ regexp *re;
+ char errstr[RXCERR_LEN];
unsigned reflags;
- const char *errstr;
- int erroffset;
+ size_t erroffset;
if(nvec < 3) {
disorder_error(0, "%s:%d: transform needs at least 3 arguments",
return -1;
}
reflags = (nvec >= 5 ? regsub_flags(vec[4]) : 0);
- if(!(re = pcre_compile(vec[1],
- PCRE_UTF8
- |regsub_compile_options(reflags),
- &errstr, &erroffset, 0))) {
- disorder_error(0, "%s:%d: compiling regexp /%s/: %s (offset %d)",
+ if(!(re = regexp_compile(vec[1], regsub_compile_options(reflags),
+ errstr, sizeof(errstr), &erroffset)))
+ {
+ disorder_error(0, "%s:%d: compiling regexp /%s/: %s (offset %zu)",
cs->path, cs->line, vec[1], errstr, erroffset);
return -1;
}
for(n = 0; n < npl->n; ++n) {
np = &npl->s[n];
xfree(np->part);
- pcre_free(np->re); /* ...whatever pcre_free is set to. */
+ regexp_free(np->re);
xfree(np->res);
xfree(np->replace);
xfree(np->context);
for(n = 0; n < tl->n; ++n) {
t = &tl->t[n];
xfree(t->type);
- pcre_free(t->re); /* ...whatever pcre_free is set to. */
+ regexp_free(t->re);
xfree(t->replace);
xfree(t->context);
}
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
-#include <pcre.h>
-
#include "speaker-protocol.h"
+#include "regexp.h"
#include "rights.h"
#include "addr.h"
/** @brief A track name part */
struct namepart {
char *part; /* part */
- pcre *re; /* compiled regexp */
+ regexp *re; /* compiled regexp */
char *res; /* regexp as a string */
char *replace; /* replacement string */
char *context; /* context glob */
char *type; /* track or dir */
char *context; /* sort or choose */
char *replace; /* substitution string */
- pcre *re; /* compiled re */
+ regexp *re; /* compiled re */
unsigned flags; /* regexp flags */
};
--- /dev/null
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2017 Mark Wooding
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/** @file lib/regexp.c
+ * @brief Regular expressions
+ */
+#include "common.h"
+
+#include "regexp.h"
+#include "mem.h"
+
+void regexp_setup(void)
+{
+ pcre_malloc = xmalloc;
+ pcre_free = xfree;
+}
+
+regexp *regexp_compile(const char *pat, unsigned f,
+ char *errbuf, size_t errlen, size_t *erroff_out)
+{
+ char *p;
+ const char *e;
+ int erroff;
+ regexp *re;
+ size_t i;
+
+ re = pcre_compile(pat, f, &e, &erroff, 0);
+ if(!re) {
+ *erroff_out = erroff;
+ for(p = errbuf, i = errlen - 1; i && *e; i--) *p++ = *e++;
+ *p = 0;
+ }
+ return re;
+}
+
+int regexp_match(const regexp *re, const char *s, size_t n, unsigned f,
+ size_t *ov, size_t on)
+{
+ int rc;
+ int *myov;
+ size_t i;
+
+ myov = xmalloc(on*sizeof(*myov));
+ rc = pcre_exec(re, 0, s, n, 0, f, myov, on);
+ for(i = 0; i < on; i++) ov[i] = myov[i];
+ xfree(myov);
+ return rc;
+}
+
+void regexp_free(regexp *re)
+ { pcre_free(re); }
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+End:
+*/
--- /dev/null
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2017 Mark Wooding
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/** @file lib/regexp.h
+ * @brief Regular expressions
+ */
+#ifndef REGEXP_H
+#define REGEXP_H
+
+#if defined(HAVE_PCRE_H)
+# include <pcre.h>
+ typedef pcre regexp;
+# define RXF_CASELESS PCRE_CASELESS
+# define RXERR_NOMATCH PCRE_ERROR_NOMATCH
+#else
+# error "no supported regular expression library found"
+#endif
+
+void regexp_setup(void);
+
+#define RXCERR_LEN 128
+regexp *regexp_compile(const char *pat, unsigned f,
+ char *errbuf, size_t errlen, size_t *erroff_out);
+
+int regexp_match(const regexp *re, const char *s, size_t n, unsigned f,
+ size_t *ov, size_t on);
+
+void regexp_free(regexp *re);
+
+#endif /* REGEXP_H */
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+End:
+*/
*/
#include "common.h"
-#include <pcre.h>
-
+#include "regexp.h"
#include "regsub.h"
#include "mem.h"
#include "vector.h"
#define PREMATCH (-1) /* fictitious pre-match substring */
#define POSTMATCH (-2) /* fictitious post-match substring */
-static inline int substring_start(const char attribute((unused)) *subject,
- const int *ovector,
- int n) {
+static inline size_t substring_start(const char attribute((unused)) *subject,
+ const size_t *ovector,
+ size_t n) {
switch(n) {
case PREMATCH: return 0;
case POSTMATCH: return ovector[1];
}
}
-static inline int substring_end(const char *subject,
- const int *ovector,
- int n) {
+static inline size_t substring_end(const char *subject,
+ const size_t *ovector,
+ size_t n) {
switch(n) {
case PREMATCH: return ovector[0];
case POSTMATCH: return strlen(subject);
static void transform_append(struct dynstr *d,
const char *subject,
- const int *ovector,
- int n) {
+ const size_t *ovector,
+ size_t n) {
int start = substring_start(subject, ovector, n);
int end = substring_end(subject, ovector, n);
static void replace_core(struct dynstr *d,
const char *subject,
const char *replace,
- int rc,
- const int *ovector) {
- int substr;
+ size_t rc,
+ const size_t *ovector) {
+ size_t substr;
while(*replace) {
if(*replace == '$')
int options = 0;
if(flags & REGSUB_CASE_INDEPENDENT)
- options |= PCRE_CASELESS;
+ options |= RXF_CASELESS;
return options;
}
-const char *regsub(const pcre *re, const char *subject, const char *replace,
- unsigned flags) {
- int rc, ovector[99], matches;
+const char *regsub(const regexp *re, const char *subject,
+ const char *replace, unsigned flags) {
+ int rc, matches;
+ size_t ovector[99];
struct dynstr d;
dynstr_init(&d);
matches = 0;
/* find the next match */
- while((rc = pcre_exec(re, 0, subject, strlen(subject), 0,
- 0, ovector, sizeof ovector / sizeof (int))) > 0) {
+ while((rc = regexp_match(re, subject, strlen(subject), 0,
+ ovector, sizeof ovector / sizeof (ovector[0]))) > 0) {
/* text just before the match */
if(!(flags & REGSUB_REPLACE))
transform_append(&d, subject, ovector, PREMATCH);
if(!(flags & REGSUB_GLOBAL))
break;
}
- if(rc <= 0 && rc != PCRE_ERROR_NOMATCH) {
- disorder_error(0, "pcre_exec returned %d, subject '%s'", rc, subject);
+ if(rc <= 0 && rc != RXERR_NOMATCH) {
+ disorder_error(0, "regexp_match returned %d, subject '%s'", rc, subject);
return 0;
}
if((flags & REGSUB_MUST_MATCH) && matches == 0)
#ifndef REGSUB_H
#define REGSUB_H
-#include <pcre.h>
+#include "regexp.h"
#define REGSUB_GLOBAL 0x0001 /* global replace */
#define REGSUB_MUST_MATCH 0x0002 /* return 0 if no match */
int regsub_compile_options(unsigned flags);
/* convert compile-time options */
-const char *regsub(const pcre *re, const char *subject, const char *replace,
- unsigned flags);
+const char *regsub(const regexp *re, const char *subject,
+ const char *replace, unsigned flags);
#endif /* REGSUB_H */
#include <db.h>
#include <sys/socket.h>
-#include <pcre.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>
#include "event.h"
#include "mem.h"
+#include "regexp.h"
#include "kvp.h"
#include "log.h"
#include "vector.h"
* If @p re is NULL then always matches.
*/
static int track_matches(size_t dl, const char *track, size_t tl,
- const pcre *re) {
- int ovec[3], rc;
+ const regexp *re) {
+ size_t ovec[3];
+ int rc;
if(!re)
return 1;
track += dl + 1;
tl -= (dl + 1);
- switch(rc = pcre_exec(re, 0, track, tl, 0, 0, ovec, 3)) {
- case PCRE_ERROR_NOMATCH: return 0;
+ switch(rc = regexp_match(re, track, tl, 0, ovec, 3)) {
+ case RXERR_NOMATCH: return 0;
default:
if(rc < 0) {
- disorder_error(0, "pcre_exec returned %d, subject '%s'", rc, track);
+ disorder_error(0, "regexp_match returned %d, subject '%s'", rc, track);
return 0;
}
return 1;
* @return 0 or DB_LOCK_DEADLOCK
*/
static int do_list(struct vector *v, const char *dir,
- enum trackdb_listable what, const pcre *re, DB_TXN *tid) {
+ enum trackdb_listable what, const regexp *re, DB_TXN *tid) {
DBC *cursor;
DBT k, d;
size_t dl;
* @return List of tracks
*/
char **trackdb_list(const char *dir, int *np, enum trackdb_listable what,
- const pcre *re) {
+ const regexp *re) {
DB_TXN *tid;
int n;
struct vector v;
#ifndef TRACKDB_H
#define TRACKDB_H
-#include <pcre.h>
-
#include "event.h"
+#include "regexp.h"
#include "rights.h"
extern const struct cache_type cache_files_type;
};
char **trackdb_list(const char *dir, int *np, enum trackdb_listable what,
- const pcre *rec);
+ const regexp *rec);
/* Return the directories and/or files below DIR. If DIR is a null pointer
* then concatenate the listing of all collections.
*
#include "test.h"
static void test_regsub(void) {
- pcre *re;
- const char *errstr;
- int erroffset;
+ regexp *re;
+ char errstr[RXCERR_LEN];
+ size_t erroffset;
check_integer(regsub_flags(""), 0);
check_integer(regsub_flags("g"), REGSUB_GLOBAL);
check_integer(regsub_flags("gi"), REGSUB_GLOBAL|REGSUB_CASE_INDEPENDENT);
check_integer(regsub_flags("iiggxx"), REGSUB_GLOBAL|REGSUB_CASE_INDEPENDENT);
check_integer(regsub_compile_options(0), 0);
- check_integer(regsub_compile_options(REGSUB_CASE_INDEPENDENT), PCRE_CASELESS);
- check_integer(regsub_compile_options(REGSUB_GLOBAL|REGSUB_CASE_INDEPENDENT), PCRE_CASELESS);
+ check_integer(regsub_compile_options(REGSUB_CASE_INDEPENDENT), RXF_CASELESS);
+ check_integer(regsub_compile_options(REGSUB_GLOBAL|REGSUB_CASE_INDEPENDENT), RXF_CASELESS);
check_integer(regsub_compile_options(REGSUB_GLOBAL), 0);
- re = pcre_compile("foo", PCRE_UTF8, &errstr, &erroffset, 0);
+ re = regexp_compile("foo", 0, errstr, sizeof(errstr), &erroffset);
assert(re != 0);
check_string(regsub(re, "wibble-foo-foo-bar", "spong", 0),
"wibble-spong-foo-bar");
"wibble-x-x-bar");
insist(regsub(re, "wibble-x-x-bar", "spong", REGSUB_MUST_MATCH) == 0);
- re = pcre_compile("a+", PCRE_UTF8, &errstr, &erroffset, 0);
+ re = regexp_compile("a+", 0, errstr, sizeof(errstr), &erroffset);
assert(re != 0);
check_string(regsub(re, "baaaaa", "spong", 0),
"bspong");
check_string(regsub(re, "baaaaa", "foo-$&-bar$x", 0),
"bfoo-aaaaa-bar$x");
- re = pcre_compile("(a+)(b+)", PCRE_UTF8|PCRE_CASELESS, &errstr, &erroffset, 0);
+ re = regexp_compile("(a+)(b+)", RXF_CASELESS,
+ errstr, sizeof(errstr), &erroffset);
assert(re != 0);
check_string(regsub(re, "foo-aaaabbb-bar", "spong", 0),
"foo-spong-bar");
#include <netdb.h>
#include <netinet/in.h>
#include <sys/un.h>
-#include <pcre.h>
#include <setjmp.h>
#include "mem.h"
#include "addr.h"
#include "base64.h"
#include "url.h"
+#include "regexp.h"
#include "regsub.h"
extern long long tests, errors;
if(!setlocale(LC_CTYPE, ""))
disorder_fatal(errno, "error calling setlocale");
/* garbage-collect PCRE's memory */
- pcre_malloc = xmalloc;
- pcre_free = xfree;
+ regexp_setup();
while((n = getopt_long(argc, argv, "hVc:dfP:NsW", options, 0)) >= 0) {
switch(n) {
case 'h': help();
char **vec,
int nvec,
enum trackdb_listable what) {
- const char *dir, *re, *errstr;
- int erroffset;
- pcre *rec;
+ const char *dir, *re;
+ char errstr[RXCERR_LEN];
+ size_t erroffset;
+ regexp *rec;
char **fvec, *key;
switch(nvec) {
} else {
/* Cache miss, we'll do the lookup and key != 0 so we'll store the answer
* in the cache. */
- if(!(rec = pcre_compile(re, PCRE_CASELESS|PCRE_UTF8,
- &errstr, &erroffset, 0))) {
+ if(!(rec = regexp_compile(re, RXF_CASELESS,
+ errstr, sizeof(errstr), &erroffset))) {
sink_printf(ev_writer_sink(c->w), "550 Error compiling regexp: %s\n",
errstr);
return 1;