summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--channel.c67
-rw-r--r--channel.h23
-rw-r--r--config.c60
-rw-r--r--config.h1
-rw-r--r--regexset.c6
-rw-r--r--regexset.h3
7 files changed, 161 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 18950d1..92d2043 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/config.c b/config.c
index fbcc935..3d683c2 100644
--- a/config.c
+++ b/config.c
@@ -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;
}
diff --git a/config.h b/config.h
index 21c2651..486919c 100644
--- a/config.h
+++ b/config.h
@@ -2,5 +2,6 @@
#define _CONFIG_H_
int cfg_init();
+void cfg_free();
#endif
diff --git a/regexset.c b/regexset.c
index 40ad077..657978a 100644
--- a/regexset.c
+++ b/regexset.c
@@ -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 ? &regexes[index] : NULL);
+}
+
void rs_free() {
for(int i = 0; i < rs_count; i++) {
pcre_free(regexes[i].text);
diff --git a/regexset.h b/regexset.h
index 23b933e..14d158f 100644
--- a/regexset.h
+++ b/regexset.h
@@ -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