summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--config.c15
-rw-r--r--main.c6
-rw-r--r--regexset.c60
-rw-r--r--regexset.h15
5 files changed, 95 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index df491b2..18950d1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
CC = gcc
LD = gcc
-CFLAGS += -std=c99 $(shell pkg-config --cflags libconfig)
+CFLAGS += -std=c99
+CFLAGS += $(shell pkg-config --cflags libconfig)
+CFLAGS += $(shell pcre-config --cflags)
LDFLAGS += $(shell pkg-config --libs libconfig)
-OBJECTS = main.o config.o
+LDFLAGS += $(shell pcre-config --libs)
+OBJECTS = main.o config.o regexset.o
TARGET = ircstats
all: $(TARGET)
diff --git a/config.c b/config.c
index ea574fb..437d993 100644
--- a/config.c
+++ b/config.c
@@ -3,6 +3,8 @@
#include <libconfig.h>
+#include "regexset.h"
+
config_t config;
int cfg_init() {
@@ -12,20 +14,19 @@ int cfg_init() {
strcpy(cfg_file, getenv("HOME"));
strcat(cfg_file, "/.ircstats/config");
- if(config_read_file(&config, cfg_file) == CONFIG_TRUE) {
- return 1;
- } else {
+ if(config_read_file(&config, cfg_file) == CONFIG_FALSE) {
int line = config_error_line(&config);
if(line == 0)
fprintf(stderr, "Could not read config: %s\n", config_error_text(&config));
else
fprintf(stderr, "Parse error on line %d: %s\n", config_error_line(&config), config_error_text(&config));
+ return 0;
}
config_setting_t *regexes_setting = config_lookup(&config, "regexes");
if(!config_setting_is_aggregate(regexes_setting)) {
fprintf(stderr, "Setting \"regexes\" must be an aggregate type.\n");
- return 1;
+ return 0;
}
int regex_count = config_setting_length(regexes_setting);
@@ -35,10 +36,12 @@ int cfg_init() {
const char *text, *join;
if(!(config_setting_lookup_string(re_setting, "text", &text) && config_setting_lookup_string(re_setting, "join", &join))) {
fprintf(stderr, "Regex set #%d missing one or more keys.\n", i+1);
- continue;
+ return 0;
}
+ if(!rs_add(text, join))
+ return 0;
}
- return 0;
+ return 1;
}
diff --git a/main.c b/main.c
index a6e9019..93d5738 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,15 @@
#include <stdio.h>
#include "config.h"
+#include "regexset.h"
int main(int argc, char **argv) {
+ /* Regex sets must be initialized before config. */
+ rs_init();
if(!cfg_init()) {
+ /* Free any registered regex sets when config fails.
+ Config will fail if a regex set fails to compile all parts. */
+ rs_free();
return 1;
}
return 0;
diff --git a/regexset.c b/regexset.c
new file mode 100644
index 0000000..3eafb74
--- /dev/null
+++ b/regexset.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "regexset.h"
+
+struct regexset_t *regexes;
+int rs_count;
+
+void rs_init() {
+ regexes = NULL;
+ rs_count = 0;
+}
+
+static inline void re_error(const char *name, const char *pattern, const char *error, int erroffset) {
+ fprintf(stderr, "RE \"%s\" failed to compile: %s\n", name, error);
+ fprintf(stderr, "%s\n", pattern);
+ for(int i = 0; i < erroffset; i++) fprintf(stderr, " ");
+ fprintf(stderr, "^\n");
+ regexes = realloc(regexes, --rs_count * sizeof(struct regexset_t));
+}
+
+struct regexset_t *rs_add(const char *text, const char *join) {
+ regexes = realloc(regexes, ++rs_count * sizeof(struct regexset_t));
+ if(!regexes) {
+ /* If we end up here, we cannot free any previously compiled pcre patterns. */
+ char *error = strerror(errno);
+ fprintf(stderr, "Could not (re)allocate memory for regex sets: %s\n", error);
+ return NULL;
+ }
+ /* Fetch the last struct. */
+ struct regexset_t *rs = &regexes[rs_count-1];
+ const char *error;
+ int erroffset;
+
+ rs->text = pcre_compile(text, 0, &error, &erroffset, NULL);
+ if(rs->text == NULL) {
+ re_error("text", text, error, erroffset);
+ return NULL;
+ }
+
+ /* Free compiled patterns from this point when failing. */
+
+ rs->join = pcre_compile(join, 0, &error, &erroffset, NULL);
+ if(rs->join == NULL) {
+ pcre_free(rs->text);
+ re_error("join", join, error, erroffset);
+ return NULL;
+ }
+
+ return rs;
+}
+
+void rs_free() {
+ for(int i = 0; i < rs_count; i++) {
+ pcre_free(regexes[i].text);
+ pcre_free(regexes[i].join);
+ }
+}
diff --git a/regexset.h b/regexset.h
new file mode 100644
index 0000000..23b933e
--- /dev/null
+++ b/regexset.h
@@ -0,0 +1,15 @@
+#ifndef _REGEXSET_H_
+#define _REGEXSEt_H_
+
+#include <pcre.h>
+
+struct regexset_t {
+ pcre *text;
+ pcre *join;
+};
+
+void rs_init();
+struct regexset_t *rs_add(const char *text, const char *join);
+void rs_free();
+
+#endif