diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | config.c | 15 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | regexset.c | 60 | ||||
-rw-r--r-- | regexset.h | 15 |
5 files changed, 95 insertions, 8 deletions
@@ -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) @@ -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; } @@ -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 = ®exes[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 |