/[mailutils]/mailutils/libsieve/comparator.c
ViewVC logotype

Diff of /mailutils/libsieve/comparator.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by gray, Thu Nov 14 14:55:49 2002 UTC revision 1.2 by gray, Fri Nov 15 14:37:36 2002 UTC
# Line 103  sieve_comparator_lookup (const char *nam Line 103  sieve_comparator_lookup (const char *nam
103    return NULL;    return NULL;
104  }  }
105    
106    static int
107    _find_comparator (void *item, void *data)
108    {
109      sieve_runtime_tag_t *tag = item;
110    
111      if (strcmp (tag->tag, "comparator") == 0)
112        {
113          *(sieve_comparator_t*)data = tag->arg->v.ptr;
114          return 1;
115        }
116      return 0;
117    }
118    
119  sieve_comparator_t  sieve_comparator_t
120  sieve_get_comparator (list_t tags)  sieve_get_comparator (list_t tags)
121  {  {
122      sieve_comparator_t comp = NULL;
123    
124      list_do (tags, _find_comparator, &comp);
125      return comp ? comp : sieve_comparator_lookup ("i;ascii-casemap",
126                                                    MU_SIEVE_MATCH_IS);
127    }
128    
129    /* Compile time support */
130    
131    struct regex_data {
132      int flags;
133      list_t list;
134    };
135    
136    static int
137    _regex_compile (void *item, void *data)
138    {
139      struct regex_data *rd = data;
140      int rc;
141      regex_t *preg = sieve_palloc (&sieve_machine->memory_pool, sizeof (*preg));
142      
143      rc = regcomp (preg, (char*)item, rd->flags);
144      if (rc)
145        {
146          size_t size = regerror (rc, preg, NULL, 0);
147          char *errbuf = malloc (size + 1);
148          if (errbuf)
149            {
150              regerror (rc, preg, errbuf, size);
151              sieve_compile_error (sieve_filename, sieve_line_num,
152                                   "regex error: %s", errbuf);
153              free (errbuf);
154            }
155          else
156             sieve_compile_error (sieve_filename, sieve_line_num,
157                                  "regex error");
158          return rc;
159        }
160    
161      list_append (rd->list, preg);
162      
163      return 0;
164    }
165    
166    static int
167    _free_regex (void *item, void *unused)
168    {
169      regfree ((regex_t*)item);
170      return 0;
171    }
172    
173    static void
174    _free_reglist (void *data)
175    {
176      list_t list = data;
177      list_do (list, _free_regex, NULL);
178      list_destroy (&list);
179    }
180    
181    int
182    sieve_match_part_checker (const char *name, list_t tags, list_t args)
183    {
184    iterator_t itr;    iterator_t itr;
185    char *compname = "i;ascii-casemap";    sieve_runtime_tag_t *match = NULL;
186    int matchtype = MU_SIEVE_MATCH_IS;    sieve_runtime_tag_t *comp = NULL;
187      sieve_comparator_t compfun;
188      char *compname;
189      
190      int matchtype;
191      int err = 0;
192        
193    if (!tags || iterator_create (&itr, tags))    if (!tags || iterator_create (&itr, tags))
194      return NULL;      return 0;
195    
196    for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr))    for (iterator_first (itr); !err && !iterator_is_done (itr);
197           iterator_next (itr))
198      {      {
199        sieve_runtime_tag_t *t;        sieve_runtime_tag_t *t;
200        iterator_current (itr, (void **)&t);        iterator_current (itr, (void **)&t);
201        switch (t->tag)        
202          if (strcmp (t->tag, "is") == 0
203              || strcmp (t->tag, "contains") == 0
204              || strcmp (t->tag, "matches") == 0
205              || strcmp (t->tag, "regex") == 0)
206          {          {
207          case TAG_COMPARATOR:            if (match)
208            compname = t->arg->v.string;              err = 1;
209            break;            else
210                          match = t;
         case TAG_IS:  
           matchtype = MU_SIEVE_MATCH_IS;  
           break;  
             
         case TAG_CONTAINS:  
           matchtype = MU_SIEVE_MATCH_CONTAINS;  
           break;  
             
         case TAG_MATCHES:  
           matchtype = MU_SIEVE_MATCH_MATCHES;  
           break;  
             
         case TAG_REGEX:  
           matchtype = MU_SIEVE_MATCH_REGEX;  
           break;  
211          }          }
212          else if (strcmp (t->tag, "comparator") == 0)
213            comp = t;
214      }      }
215    
216    iterator_destroy (&itr);    iterator_destroy (&itr);
217    return sieve_comparator_lookup (compname, matchtype);  
218      if (err)
219        {
220          sieve_compile_error (sieve_filename, sieve_line_num,
221                               "match type specified twice in call to `%s'",
222                               name);
223          return 1;
224        }
225    
226      if (!match || strcmp (match->tag, "is") == 0)
227        matchtype = MU_SIEVE_MATCH_IS;
228      else if (strcmp (match->tag, "contains") == 0)
229        matchtype = MU_SIEVE_MATCH_CONTAINS;
230      else if (strcmp (match->tag, "matches") == 0)
231        matchtype = MU_SIEVE_MATCH_MATCHES;
232      else if (strcmp (match->tag, "regex") == 0)
233        matchtype = MU_SIEVE_MATCH_REGEX;
234    
235      if (match)
236        list_remove (tags, match);
237    
238      compname = comp ? comp->arg->v.string : "i;ascii-casemap";
239      compfun = sieve_comparator_lookup (compname, matchtype);
240      if (!compfun)
241        {
242          sieve_compile_error (sieve_filename, sieve_line_num,
243                               "comparator `%s' is incompatible with match type `%s' in call to `%s'",
244                               compname, match ? match->tag : "is", name);
245          return 1;
246        }
247    
248      if (comp)
249        {
250          sieve_pfree (&sieve_machine->memory_pool, comp->arg);
251        }
252      else
253        {
254          comp = sieve_palloc (&sieve_machine->memory_pool,
255                               sizeof (*comp));
256          comp->tag = "comparator";
257          list_append (tags, comp);
258        }
259      comp->arg = sieve_value_create (SVT_POINTER, compfun);
260      
261      if (matchtype == MU_SIEVE_MATCH_REGEX)
262        {
263          /* To speed up things, compile all patterns at once.
264             Notice that it is supposed that patterns are in arg 2 */
265          sieve_value_t *val, *newval;
266          struct regex_data rd;
267          int rc;
268          
269          if (list_get (args, 1, (void**)&val))
270            return 0;
271    
272          if (strcmp (compname, "i;ascii-casemap") == 0)
273            rd.flags = REG_ICASE;
274          else
275            rd.flags = 0;
276    
277          list_create (&rd.list);
278          
279          rc = sieve_vlist_do (val, _regex_compile, &rd);
280    
281          sieve_machine_add_destructor (sieve_machine, _free_reglist, rd.list);
282    
283          if (rc)
284            return rc;
285          newval = sieve_value_create (SVT_STRING_LIST, rd.list);
286          list_replace (args, val, newval);
287        }
288      return 0;
289  }  }
290    
291  /* Particular comparators */  /* Particular comparators */

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26