]> jfr.im git - irc/quakenet/newserv.git/blob - newsearch/ns-regex.c
SearchCtx should contain 'type' - this is to make life easier when defining new searc...
[irc/quakenet/newserv.git] / newsearch / ns-regex.c
1 /*
2 * REGEX functionality
3 */
4
5 #include "newsearch.h"
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <pcre.h>
11
12 struct regex_localdata {
13 struct searchNode *targnode;
14 struct searchNode *patnode;
15 pcre *pcre;
16 pcre_extra *pcre_extra;
17 };
18
19 void *regex_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
20 void regex_free(searchCtx *ctx, struct searchNode *thenode);
21
22 struct searchNode *regex_parse(searchCtx *ctx, int argc, char **argv) {
23 struct regex_localdata *localdata;
24 struct searchNode *thenode;
25 struct searchNode *targnode, *patnode;
26 const char *err;
27 int erroffset;
28 pcre *pcre;
29 pcre_extra *pcre_extra;
30
31 if (argc<2) {
32 parseError="regex: usage: regex source pattern";
33 return NULL;
34 }
35
36 targnode=ctx->parser(ctx, argv[0]);
37 if (!(targnode = coerceNode(ctx,targnode, RETURNTYPE_STRING)))
38 return NULL;
39
40 patnode=ctx->parser(ctx, argv[1]);
41 if (!(patnode = coerceNode(ctx,patnode, RETURNTYPE_STRING))) {
42 (targnode->free)(ctx, targnode);
43 return NULL;
44 }
45
46 if (!(patnode->returntype & RETURNTYPE_CONST)) {
47 parseError="regex: only constant regexes allowed";
48 (targnode->free)(ctx, targnode);
49 (patnode->free)(ctx, patnode);
50 return NULL;
51 }
52
53 if (!(pcre=pcre_compile((char *)(patnode->exe)(ctx, patnode,NULL),
54 PCRE_CASELESS, &err, &erroffset, NULL))) {
55 parseError=err;
56 return NULL;
57 }
58
59 pcre_extra=pcre_study(pcre, 0, &err);
60
61 if (!(localdata=(struct regex_localdata *)malloc(sizeof (struct regex_localdata)))) {
62 parseError = "malloc: could not allocate memory for this search.";
63 /* make sure we pcre_free() if we're not going to use them */
64 if (pcre_extra)
65 pcre_free(pcre_extra);
66
67 if (pcre)
68 pcre_free(pcre);
69 return NULL;
70 }
71
72 localdata->targnode=targnode;
73 localdata->patnode=patnode;
74 localdata->pcre=pcre;
75 localdata->pcre_extra=pcre_extra;
76
77 if (!(thenode = (struct searchNode *)malloc(sizeof (struct searchNode)))) {
78 /* couldn't malloc() memory for thenode, so free the pcre's and localdata to avoid leakage */
79 parseError = "malloc: could not allocate memory for this search.";
80 if (localdata->pcre_extra)
81 pcre_free(localdata->pcre_extra);
82
83 if (localdata->pcre)
84 pcre_free(localdata->pcre);
85
86 free(localdata);
87 return NULL;
88 }
89
90 thenode->returntype = RETURNTYPE_BOOL;
91 thenode->localdata = localdata;
92 thenode->exe = regex_exe;
93 thenode->free = regex_free;
94
95 return thenode;
96 }
97
98 void *regex_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
99 struct regex_localdata *localdata;
100 char *target;
101
102 localdata = thenode->localdata;
103
104 target = (char *)((localdata->targnode->exe)(ctx, localdata->targnode,theinput));
105
106 if (pcre_exec(localdata->pcre, localdata->pcre_extra,target,strlen(target),0,
107 0,NULL,0)) {
108 /* didn't match */
109 return (void *)0;
110 } else {
111 return (void *)1;
112 }
113 }
114
115 void regex_free(searchCtx *ctx, struct searchNode *thenode) {
116 struct regex_localdata *localdata;
117
118 localdata=thenode->localdata;
119
120 if (localdata->pcre_extra)
121 pcre_free(localdata->pcre_extra);
122
123 if (localdata->pcre)
124 pcre_free(localdata->pcre);
125
126 (localdata->patnode->free)(ctx, localdata->patnode);
127 (localdata->targnode->free)(ctx, localdata->targnode);
128 free(localdata);
129 free(thenode);
130 }
131