source: filter.c @ 7cc1092

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 7cc1092 was 75c7e8e, checked in by Anders Kaseorg <andersk@mit.edu>, 12 years ago
Rename owl_filterelement_free to owl_filterelement_cleanup. Signed-off-by: Anders Kaseorg <andersk@mit.edu> Reviewed-by: Nelson Elhage <nelhage@mit.edu>
  • Property mode set to 100644
File size: 5.8 KB
Line 
1#include <string.h>
2#include "owl.h"
3
4owl_filter *owl_filter_new_fromstring(const char *name, const char *string)
5{
6  owl_filter *f;
7  char **argv;
8  int argc;
9
10  argv = owl_parseline(string, &argc);
11  f = owl_filter_new(name, argc, strs(argv));
12  owl_parse_delete(argv, argc);
13
14  return f;
15}
16
17owl_filter *owl_filter_new(const char *name, int argc, const char *const *argv)
18{
19  owl_filter *f;
20
21  f = owl_malloc(sizeof(owl_filter));
22
23  f->name=owl_strdup(name);
24  f->fgcolor=OWL_COLOR_DEFAULT;
25  f->bgcolor=OWL_COLOR_DEFAULT;
26
27  /* first take arguments that have to come first */
28  /* set the color */
29  while ( argc>=2 && ( !strcmp(argv[0], "-c") ||
30                       !strcmp(argv[0], "-b") ) ) {
31    if (owl_util_string_to_color(argv[1])==OWL_COLOR_INVALID) {
32      owl_function_error("The color '%s' is not available, using default.", argv[1]);
33    } else {
34      switch (argv[0][1]) {
35      case 'c':
36        f->fgcolor=owl_util_string_to_color(argv[1]);
37        break;
38      case 'b':
39        f->bgcolor=owl_util_string_to_color(argv[1]);
40        break;
41      }
42    }
43    argc-=2;
44    argv+=2;
45  }
46
47  if (!(f->root = owl_filter_parse_expression(argc, argv, NULL))) {
48    owl_filter_delete(f);
49    return NULL;
50  }
51
52  /* Now check for recursion. */
53  if (owl_filter_is_toodeep(f)) {
54    owl_function_error("Filter loop!");
55    owl_filter_delete(f);
56    return NULL;
57  }
58
59  return f;
60}
61
62
63/* A primitive expression is one without any toplevel ``and'' or ``or''s*/
64
65static owl_filterelement * owl_filter_parse_primitive_expression(int argc, const char *const *argv, int *next)
66{
67  owl_filterelement *fe, *op;
68  int i = 0, skip;
69
70  if(!argc) return NULL;
71
72  fe = owl_malloc(sizeof(owl_filterelement));
73  owl_filterelement_create(fe);
74
75  if(!strcasecmp(argv[i], "(")) {
76    i++;
77    op = owl_filter_parse_expression(argc-i, argv+i, &skip);
78    if(!op) goto err;
79    i += skip;
80    if(i >= argc) goto err;
81    if(strcasecmp(argv[i++], ")")) goto err;
82    owl_filterelement_create_group(fe, op);
83  } else if(!strcasecmp(argv[i], "not")) {
84    i++;
85    op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
86    if(!op) goto err;
87    i += skip;
88    owl_filterelement_create_not(fe, op);
89  } else if(!strcasecmp(argv[i], "true")) {
90    i++;
91    owl_filterelement_create_true(fe);
92  } else if(!strcasecmp(argv[i], "false")) {
93    i++;
94    owl_filterelement_create_false(fe);
95  } else {
96    if(argc == 1) goto err;
97    if(!strcasecmp(*argv, "filter")) {
98      owl_filterelement_create_filter(fe, *(argv+1));
99    } else if(!strcasecmp(*argv, "perl")) {
100      owl_filterelement_create_perl(fe, *(argv+1));
101    } else {
102      if(owl_filterelement_create_re(fe, *argv, *(argv+1))) {
103        goto err;
104      }
105    }
106    i += 2;
107  }
108
109  if(next) {
110    *next = i;
111  } else if(i != argc) {
112    goto err;
113  }
114  return fe;
115err:
116  owl_filterelement_cleanup(fe);
117  owl_free(fe);
118  return NULL;
119}
120
121owl_filterelement * owl_filter_parse_expression(int argc, const char *const *argv, int *next)
122{
123  int i = 0, skip;
124  owl_filterelement * op1 = NULL, * op2 = NULL, *tmp;
125
126  op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
127  i += skip;
128  if(!op1) goto err;
129
130  while(i < argc) {
131    if(strcasecmp(argv[i], "and") &&
132       strcasecmp(argv[i], "or")) break;
133    op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
134    if(!op2) goto err;
135    tmp = owl_malloc(sizeof(owl_filterelement));
136    if(!strcasecmp(argv[i], "and")) {
137      owl_filterelement_create_and(tmp, op1, op2);
138    } else {
139      owl_filterelement_create_or(tmp, op1, op2);
140    }
141    op1 = tmp;
142    op2 = NULL;
143    i += skip+1;
144  }
145
146  if(next) {
147    *next = i;
148  } else if(i != argc) {
149    goto err;
150  }
151  return op1;
152err:
153  if(op1) {
154    owl_filterelement_cleanup(op1);
155    owl_free(op1);
156  }
157  return NULL;
158}
159
160const char *owl_filter_get_name(const owl_filter *f)
161{
162  return(f->name);
163}
164
165SV *owl_filter_to_sv(const owl_filter *f)
166{
167  return owl_new_sv(owl_filter_get_name(f));
168}
169
170void owl_filter_set_fgcolor(owl_filter *f, int color)
171{
172  f->fgcolor=color;
173}
174
175int owl_filter_get_fgcolor(const owl_filter *f)
176{
177  return(f->fgcolor);
178}
179
180void owl_filter_set_bgcolor(owl_filter *f, int color)
181{
182  f->bgcolor=color;
183}
184
185int owl_filter_get_bgcolor(const owl_filter *f)
186{
187  return(f->bgcolor);
188}
189
190/* return 1 if the message matches the given filter, otherwise
191 * return 0.
192 */
193int owl_filter_message_match(const owl_filter *f, const owl_message *m)
194{
195  int ret;
196  if(!f->root) return 0;
197  ret = owl_filterelement_match(f->root, m);
198  return ret;
199}
200
201
202char* owl_filter_print(const owl_filter *f)
203{
204  GString *out = g_string_new("");
205
206  if (f->fgcolor!=OWL_COLOR_DEFAULT) {
207    g_string_append(out, "-c ");
208    if (f->fgcolor < 8) {
209      g_string_append(out, owl_util_color_to_string(f->fgcolor));
210    }
211    else {
212      g_string_append_printf(out, "%i",f->fgcolor);
213    }
214    g_string_append(out, " ");
215  }
216  if (f->bgcolor!=OWL_COLOR_DEFAULT) {
217    g_string_append(out, "-b ");
218    if (f->bgcolor < 8) {
219      g_string_append(out, owl_util_color_to_string(f->bgcolor));
220    }
221    else {
222      g_string_append_printf(out, "%i",f->fgcolor);
223    }
224    g_string_append(out, " ");
225  }
226  if(f->root) {
227    owl_filterelement_print(f->root, out);
228    g_string_append(out, "\n");
229  }
230
231  return g_string_free(out, 0);
232}
233
234/* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */
235int owl_filter_equiv(const owl_filter *a, const owl_filter *b)
236{
237  char *buffa, *buffb;
238  int ret;
239
240  buffa = owl_filter_print(a);
241  buffb = owl_filter_print(b);
242
243  ret = !strcmp(buffa, buffb);
244  ret = ret && !strcmp(owl_filter_get_name(a),
245                       owl_filter_get_name(b));
246
247  owl_free(buffa);
248  owl_free(buffb);
249
250  return ret;
251}
252
253
254int owl_filter_is_toodeep(const owl_filter *f)
255{
256  return owl_filterelement_is_toodeep(f, f->root);
257}
258
259void owl_filter_delete(owl_filter *f)
260{
261  if (f == NULL)
262    return;
263  if (f->root) {
264    owl_filterelement_cleanup(f->root);
265    owl_free(f->root);
266  }
267  if (f->name)
268    owl_free(f->name);
269  owl_free(f);
270}
Note: See TracBrowser for help on using the repository browser.