source: filter.c @ b470451

release-1.10release-1.8release-1.9
Last change on this file since b470451 was d427f08, checked in by Nelson Elhage <nelhage@mit.edu>, 13 years ago
Use G_GNUC_WARN_UNUSED_RESULT Have gcc warn us when we ignore the result of a function that requires the caller to free the result, or an initilization function that can fail. This might help (slightly) with preventing leaks and segfaults. Additionally changed some functions that should never fail to not return values. (The owl_list_* functions changed only fail if list->size < 0, which we assume is not the case elsewhere.)
  • 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  g_strfreev(argv);
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 = g_new(owl_filter, 1);
22
23  f->name=g_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 = g_new(owl_filterelement, 1);
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  g_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 = g_new(owl_filterelement, 1);
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    g_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 G_GNUC_WARN_UNUSED_RESULT *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  g_free(buffa);
248  g_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    g_free(f->root);
266  }
267  if (f->name)
268    g_free(f->name);
269  g_free(f);
270}
Note: See TracBrowser for help on using the repository browser.