diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | channel.c | 67 | ||||
-rw-r--r-- | channel.h | 23 | ||||
-rw-r--r-- | config.c | 60 | ||||
-rw-r--r-- | config.h | 1 | ||||
-rw-r--r-- | regexset.c | 6 | ||||
-rw-r--r-- | regexset.h | 3 |
7 files changed, 161 insertions, 4 deletions
@@ -1,11 +1,12 @@ CC = gcc LD = gcc -CFLAGS += -std=c99 +CFLAGS += -std=c99 -g +CFLAGS += -D_GNU_SOURCE CFLAGS += $(shell pkg-config --cflags libconfig) CFLAGS += $(shell pcre-config --cflags) LDFLAGS += $(shell pkg-config --libs libconfig) LDFLAGS += $(shell pcre-config --libs) -OBJECTS = main.o config.o regexset.o +OBJECTS = main.o config.o regexset.o channel.o TARGET = ircstats all: $(TARGET) diff --git a/channel.c b/channel.c new file mode 100644 index 0000000..cab4612 --- /dev/null +++ b/channel.c @@ -0,0 +1,67 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include "channel.h" + +struct channel_t *channels; +int channel_count; + +void channel_init() { + channels = NULL; + channel_count = 0; +} + +struct channel_t *channel_add(const char *name) { + channels = realloc(channels, ++channel_count * sizeof(struct regexset_t)); + if(!channels) { + char *error = strerror(errno); + fprintf(stderr, "Could not (re)allocate memory for channels: %s\n", error); + return NULL; + } + struct channel_t *channel = &channels[channel_count-1]; + channel->name = strdup(name); + channel->file_count = 0; + channel->files = NULL; + return channel; +} + +int channel_set_file_count(struct channel_t *channel, int count) { + channel->files = malloc(count * sizeof(struct channel_file_t)); + if(!channel->files) { + char *error = strerror(errno); + fprintf(stderr, "Could not allocate memory for channel files (%s): %s\n", channel->name, error); + return 0; + } + channel->file_count = count; + return 1; +} + +int channel_set_file(struct channel_t *channel, int index, const char *path, int rs_index) { + struct channel_file_t *file; + /* Make sure index is in range. */ + if(!(index < channel->file_count)) + return 0; + file = &channel->files[index]; + file->path = strdup(path); + file->rs = rs_get(rs_index); + /* Fail if we don't get a regex set. */ + if(!file->rs) + return 0; + return 1; +} + +void channel_free() { + for(int i = 0; i < channel_count; i++) { + free(channels[i].name); + /* Free all file path strings. */ + for(int j = 0; j < channels[i].file_count; j++) { + free(channels[i].files[j].path); + } + /* 'files' is a dynamically allocated array, must be freed. */ + free(channels[i].files); + } + free(channels); + channels = NULL; +} diff --git a/channel.h b/channel.h new file mode 100644 index 0000000..cda0df5 --- /dev/null +++ b/channel.h @@ -0,0 +1,23 @@ +#ifndef _CHANNEL_H_ +#define _CHANNEL_H_ + +#include "regexset.h" + +struct channel_file_t { + char *path; + struct regexset_t *rs; +}; + +struct channel_t { + char *name; + int file_count; + struct channel_file_t *files; +}; + +void channel_init(); +struct channel_t *channel_add(const char *name); +int channel_set_file_count(struct channel_t *channel, int count); +int channel_set_file(struct channel_t *channel, int index, const char *path, int rs_index); +void channel_free(); + +#endif @@ -4,6 +4,7 @@ #include <libconfig.h> #include "regexset.h" +#include "channel.h" config_t config; @@ -42,6 +43,65 @@ int cfg_init() { return 0; } + config_setting_t *channels_setting = config_lookup(&config, "channels"); + if(!config_setting_is_aggregate(channels_setting)) { + fprintf(stderr, "Setting \"channels\" must be an aggregate type.\n"); + return 0; + } + + int channel_count = config_setting_length(channels_setting); + for(int i = 0; i < channel_count; i++) { + config_setting_t *channel_setting = config_setting_get_elem(channels_setting, i); + const char *name; + if(!config_setting_lookup_string(channel_setting, "name", &name)) { + char *sname; + sname = malloc(sizeof(char) * 16); + sprintf(sname, "channel #%d", i+1); + name = sname; + } + printf("Channel %s\n", name); + struct channel_t *channel; + if(!(channel = channel_add(name))) { + return 0; + } + config_setting_t *files = config_setting_get_member(channel_setting, "files"); + if(!config_setting_is_aggregate(files)) { + fprintf(stderr, "Setting \"files\" must be an aggregate type (no files added).\n", name); + continue; + } + int file_count = config_setting_length(files); + /* Break if we can't set file count, most likely any following channels will also fail. */ + if(!channel_set_file_count(channel, file_count)) + break; + /* Iterate through files. */ + for(int j = 0; j < file_count; j++) { + const char *filepath; + int rs_index; + config_setting_t *file = config_setting_get_elem(files, j); + /* (filepath, regexset) pair. */ + if(config_setting_is_aggregate(file)) { + if(config_setting_length(file) != 2) { + fprintf(stderr, "File lists must have exactly two elements.\n"); + continue; + } + config_setting_t *path_setting = config_setting_get_elem(file, 0); + config_setting_t *rs_setting = config_setting_get_elem(file, 1); + if(!(config_setting_type(path_setting) == CONFIG_TYPE_STRING && config_setting_type(rs_setting) == CONFIG_TYPE_INT)) { + fprintf(stderr, "File lists must have a string and an integer.\n"); + continue; + } + filepath = config_setting_get_string(path_setting); + rs_index = config_setting_get_int(rs_setting); + } else { /* filepath only. */ + filepath = config_setting_get_string(file); + rs_index = 0; + } + if(!channel_set_file(channel, j, filepath, rs_index)) { + fprintf(stderr, "Failed to set file #%d (%s) for channel %s.\n", j+1, filepath, name); + } + } + } + return 1; } @@ -2,5 +2,6 @@ #define _CONFIG_H_ int cfg_init(); +void cfg_free(); #endif @@ -13,7 +13,7 @@ void rs_init() { rs_count = 0; } -static inline void re_error(const char *name, const char *pattern, const char *error, int erroffset) { +static 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, " "); @@ -52,6 +52,10 @@ struct regexset_t *rs_add(const char *text, const char *join) { return rs; } +struct regexset_t *rs_get(int index) { + return (index < rs_count ? ®exes[index] : NULL); +} + void rs_free() { for(int i = 0; i < rs_count; i++) { pcre_free(regexes[i].text); @@ -1,5 +1,5 @@ #ifndef _REGEXSET_H_ -#define _REGEXSEt_H_ +#define _REGEXSET_H_ #include <pcre.h> @@ -10,6 +10,7 @@ struct regexset_t { void rs_init(); struct regexset_t *rs_add(const char *text, const char *join); +struct regexset_t *rs_get(int index); void rs_free(); #endif |