summaryrefslogtreecommitdiff
path: root/regexset.c
blob: 61a22be382b2e2b73d09ce443c7ec443a3cc0fdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#include "regexset.h"

struct regexset_t *regexes;
int rs_count;
const unsigned char *rs_pcre_tables;

void rs_init() {
	regexes = NULL;
	rs_count = 0;
	rs_pcre_tables = pcre_maketables();
}

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, " ");
	fprintf(stderr, "^\n");
	regexes = realloc(regexes, --rs_count * sizeof(struct regexset_t));
}

struct regexset_t *rs_add(const char *text, const char *join, const char *kick) {
	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, rs_pcre_tables);
	if(rs->text == NULL) {
		re_error("text", text, error, erroffset);
		return NULL;
	}
	rs->text_e = pcre_study(rs->text, 0, &error);

	/* Free compiled patterns from this point when failing. */

	rs->join = pcre_compile(join, 0, &error, &erroffset, rs_pcre_tables);
	if(rs->join == NULL) {
		pcre_free(rs->text);
		if(rs->text_e)
			pcre_free(rs->text_e);
		re_error("join", join, error, erroffset);
		return NULL;
	}
	rs->join_e = pcre_study(rs->join, 0, &error);

	rs->kick = pcre_compile(kick, 0, &error, &erroffset, rs_pcre_tables);
	if(rs->kick == NULL) {
		pcre_free(rs->text);
		pcre_free(rs->join);
		if(rs->text_e) {
			pcre_free(rs->text_e);
			pcre_free(rs->join_e);
		}
		re_error("kick", kick, error, erroffset);
		return NULL;

	}
	rs->kick_e = pcre_study(rs->kick, 0, &error);

	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);
		if(regexes[i].text_e)
			pcre_free(regexes[i].text_e);
		pcre_free(regexes[i].join);
		if(regexes[i].join_e)
			pcre_free(regexes[i].join_e);
		pcre_free(regexes[i].kick);
		if(regexes[i].kick_e)
			pcre_free(regexes[i].kick_e);
	}
	free(regexes);
	regexes = NULL;
	pcre_free((void*)rs_pcre_tables);
	rs_pcre_tables = NULL;
}