summaryrefslogtreecommitdiff
path: root/nick.c
blob: 088edca4eae4e3a339ead30b63afb08f95a46dca (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
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#include "nick.h"

struct nick_t *nicks;
const unsigned char *nick_pcre_tables;

void nick_init() {
	nicks = NULL;
	nick_pcre_tables = pcre_maketables();
}

struct nick_t *nick_add(const char *name) {
	struct nick_t *nick = malloc(sizeof(struct nick_t));
	if(!nick) {
		char *error = strerror(errno);
		fprintf(stderr, "Could not allocate memory for nick: %s\n", error);
		return NULL;
	}

	if(nicks) {
		struct nick_t *n = nicks;
		while(n->next) n = n->next;
		n->next = nick;
	} else
		nicks = nick;

	nick->name = strdup(name);
	nick->regexes = NULL;
	nick->next = NULL;

	return nick;
}

int nick_regex_add(struct nick_t *nick, const char *re_s) {
	struct nick_regex_t *nre = malloc(sizeof(struct nick_regex_t));
	if(!nre) {
		char *error = strerror(errno);
		fprintf(stderr, "Could not allocate memory for nick regex: %s\n", error);
		return 0;
	}

	const char *error;
	int erroffset;
	nre->re = pcre_compile(re_s, 0, &error, &erroffset, nick_pcre_tables);
	if(!nre->re) {
		/* Copied from re_error in regexset.c */
		fprintf(stderr, "Nick RE failed to compile: %s\n", error);
		fprintf(stderr, "%s\n", re_s);
		for(int i = 0; i < erroffset; i++) fprintf(stderr, " ");
		fprintf(stderr, "^\n");
		free(nre);
		return 0;
	}
	nre->re_e = pcre_study(nre->re, 0, &error);

	nre->next = NULL;

	if(nick->regexes) {
		struct nick_regex_t *n = nick->regexes;
		while(n->next) n = n->next;
		n->next = nre;
	} else
		nick->regexes = nre;

	return 1;
}

char *nick_get(char *name) {
	struct nick_t *nick = nicks;
	while(nick) {
		struct nick_regex_t *nre = nick->regexes;
		while(nre) {
			int ovector[6];
			int rc;
			rc = pcre_exec(nre->re, nre->re_e, name, strlen(name), 0, 0, ovector, 6);
			if(rc > 0)
				return nick->name;
			nre = nre->next;
		}
		nick = nick->next;
	}
	return name;
}

void nick_free() {
	struct nick_t *nick = nicks;
	while(nick) {
		free(nick->name);
		struct nick_regex_t *re = nick->regexes;
		while(re) {
			pcre_free(re->re);
			if(re->re_e)
				pcre_free(re->re_e);
			struct nick_regex_t *next = re->next;
			free(re);
			re = next;
		}
		struct nick_t *next = nick->next;
		free(nick);
		nick = next;
	}
	nicks = NULL; // nicks already free'd by first iteration
	pcre_free((void*)nick_pcre_tables);
}