Commit e2bd3a05 e2bd3a059eb8268d156baf59e41909cae1e28297 by Sergey Poznyakoff

sieve: redo symbol registry support.

The purpose is to simplify the machine structure and to ensure its
clones are completely independent of the master instance.

* include/mailutils/sieve.h (mu_sieve_command): New struct.
(mu_sieve_record): New enum
(mu_sieve_registry_t): Generalize for storing various types of objects.
(mu_sieve_test_lookup,mu_sieve_action_lookup)
(mu_sieve_require_action,mu_sieve_require_test)
(mu_sieve_require_comparator): Remove.
(mu_sieve_register_test_ext,mu_sieve_register_test)
(mu_sieve_register_action_ext,mu_sieve_register_action)
(mu_sieve_register_comparator)
(mu_sieve_load_ext): Change return type.
(mu_sieve_registry_require,mu_sieve_unload_ext): New functions.
(mu_sieve_machine_inherit): Rename to mu_sieve_machine_clone.
* libmu_sieve/sieve-priv.h (mu_sieve_machine): Remove source_list,
test_list, action_list, and comp_list.  Add a single registry list
instead.
Add space for file and command (action and test) names: idspace,
idcount, idmax.
Remove unused field "stack";
(mu_i_sv_lex_finish): Change prototype.
(_mu_i_sv_instr_push,_mu_i_sv_instr_pop): Remove protos.
(mu_i_sv_id_canon,mu_i_sv_id_num)
(mu_i_sv_id_str,mu_i_sv_free_idspace): New protos.
* libmu_sieve/register.c: Rename to registry.c
* libmu_sieve/registry.c (mu_sieve_test_lookup)
(mu_sieve_action_lookup): Remove.
(mu_sieve_require_test,mu_sieve_require_action): Remove.
(mu_sieve_registry_require): New function.
(mu_sieve_registry_add,mu_sieve_registry_lookup): New functions.
* libmu_sieve/Makefile.am: Update.
* libmu_sieve/comparator.c: Rewrite using new registry functions.
* libmu_sieve/load.c (mu_sieve_load_ext): Return module handle.
(mu_sieve_unload_ext): New function.
* libmu_sieve/mem.c (mu_sieve_free): Gracefully handle NULL argument.
(mu_i_sv_id_canon,mu_i_sv_id_num,mu_i_sv_id_str): New functions.
* libmu_sieve/prog.c (mu_i_sv_locus): Store index of the file name in
the id space, instead of pointer to the name itself.

* libmu_sieve/require.c (mu_sieve_require): Rewrite.
* libmu_sieve/runtime.c (_mu_i_sv_instr_source): Expect ID index
as argument.
(_mu_i_sv_instr_push)
(_mu_i_sv_instr_pop): Remove unused instructions.

* libmu_sieve/sieve.l (file_names): Remove.  Use mu_sieve_machine
idspace instead.
* libmu_sieve/sieve.y (mu_sieve_machine_clone)
(mu_sieve_machine_dup): Rewrite.
(mu_sieve_machine_destroy): Free idspace and registry

* examples/numaddr.c: Reflect changes.
* libmu_sieve/extensions/editheader.c: Likewise.
* libmu_sieve/extensions/list.c: Likewise.
* libmu_sieve/extensions/moderator.c: Likewise.
* libmu_sieve/extensions/pipe.c: Likewise.
* libmu_sieve/extensions/spamd.c: Likewise.
* libmu_sieve/extensions/timestamp.c: Likewise.
* libmu_sieve/extensions/vacation.c: Likewise.
1 parent fdf02db3
...@@ -131,6 +131,7 @@ static mu_sieve_tag_group_t numaddr_tag_groups[] = { ...@@ -131,6 +131,7 @@ static mu_sieve_tag_group_t numaddr_tag_groups[] = {
131 int 131 int
132 SIEVE_EXPORT(numaddr,init) (mu_sieve_machine_t mach) 132 SIEVE_EXPORT(numaddr,init) (mu_sieve_machine_t mach)
133 { 133 {
134 return mu_sieve_register_test (mach, "numaddr", numaddr_test, 134 mu_sieve_register_test (mach, "numaddr", numaddr_test,
135 numaddr_req_args, numaddr_tag_groups, 1); 135 numaddr_req_args, numaddr_tag_groups, 1);
136 return 0;
136 } 137 }
......
...@@ -100,17 +100,13 @@ typedef struct ...@@ -100,17 +100,13 @@ typedef struct
100 mu_sieve_tag_checker_t checker; 100 mu_sieve_tag_checker_t checker;
101 } mu_sieve_tag_group_t; 101 } mu_sieve_tag_group_t;
102 102
103 typedef struct 103 struct mu_sieve_command /* test or action */
104 { 104 {
105 const char *name;
106 int required;
107 mu_sieve_handler_t handler; 105 mu_sieve_handler_t handler;
108 mu_sieve_data_type *req_args; 106 mu_sieve_data_type *req_args;
109 mu_sieve_data_type *opt_args; 107 mu_sieve_data_type *opt_args;
110 mu_sieve_tag_group_t *tags; 108 mu_sieve_tag_group_t *tags;
111 } mu_sieve_register_t; 109 };
112
113 #define MU_SIEVE_CHARSET "UTF-8"
114 110
115 #define MU_SIEVE_MATCH_IS 1 111 #define MU_SIEVE_MATCH_IS 1
116 #define MU_SIEVE_MATCH_CONTAINS 2 112 #define MU_SIEVE_MATCH_CONTAINS 2
...@@ -119,6 +115,28 @@ typedef struct ...@@ -119,6 +115,28 @@ typedef struct
119 #define MU_SIEVE_MATCH_EQ 5 115 #define MU_SIEVE_MATCH_EQ 5
120 #define MU_SIEVE_MATCH_LAST 6 116 #define MU_SIEVE_MATCH_LAST 6
121 117
118 enum mu_sieve_record
119 {
120 mu_sieve_record_action,
121 mu_sieve_record_test,
122 mu_sieve_record_comparator
123 };
124
125 typedef struct
126 {
127 const char *name;
128 int required;
129 void *handle;
130 enum mu_sieve_record type;
131 union
132 {
133 struct mu_sieve_command command;
134 mu_sieve_comparator_t comp[MU_SIEVE_MATCH_LAST];
135 } v;
136 } mu_sieve_registry_t;
137
138 #define MU_SIEVE_CHARSET "UTF-8"
139
122 extern mu_debug_handle_t mu_sieve_debug_handle; 140 extern mu_debug_handle_t mu_sieve_debug_handle;
123 extern mu_list_t mu_sieve_include_path; 141 extern mu_list_t mu_sieve_include_path;
124 extern mu_list_t mu_sieve_library_path; 142 extern mu_list_t mu_sieve_library_path;
...@@ -143,41 +161,46 @@ size_t mu_sieve_value_create (mu_sieve_machine_t mach, ...@@ -143,41 +161,46 @@ size_t mu_sieve_value_create (mu_sieve_machine_t mach,
143 mu_sieve_data_type type, void *data); 161 mu_sieve_data_type type, void *data);
144 162
145 /* Symbol space functions */ 163 /* Symbol space functions */
146 mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach, 164 mu_sieve_registry_t *mu_sieve_registry_add (mu_sieve_machine_t mach,
147 const char *name);
148 mu_sieve_register_t *mu_sieve_action_lookup (mu_sieve_machine_t mach,
149 const char *name); 165 const char *name);
150 int mu_sieve_register_test_ext (mu_sieve_machine_t mach, 166 mu_sieve_registry_t *mu_sieve_registry_lookup (mu_sieve_machine_t mach,
167 const char *name,
168 enum mu_sieve_record type);
169 int mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name,
170 enum mu_sieve_record type);
171
172 void mu_sieve_register_test_ext (mu_sieve_machine_t mach,
151 const char *name, mu_sieve_handler_t handler, 173 const char *name, mu_sieve_handler_t handler,
152 mu_sieve_data_type *req_args, 174 mu_sieve_data_type *req_args,
153 mu_sieve_data_type *opt_args, 175 mu_sieve_data_type *opt_args,
154 mu_sieve_tag_group_t *tags, int required); 176 mu_sieve_tag_group_t *tags, int required);
155 int mu_sieve_register_test (mu_sieve_machine_t mach, 177 void mu_sieve_register_test (mu_sieve_machine_t mach,
156 const char *name, mu_sieve_handler_t handler, 178 const char *name, mu_sieve_handler_t handler,
157 mu_sieve_data_type *arg_types, 179 mu_sieve_data_type *arg_types,
158 mu_sieve_tag_group_t *tags, int required); 180 mu_sieve_tag_group_t *tags, int required);
159 181
160 int mu_sieve_register_action_ext (mu_sieve_machine_t mach, 182 void mu_sieve_register_action_ext (mu_sieve_machine_t mach,
161 const char *name, mu_sieve_handler_t handler, 183 const char *name, mu_sieve_handler_t handler,
162 mu_sieve_data_type *req_args, 184 mu_sieve_data_type *req_args,
163 mu_sieve_data_type *opt_args, 185 mu_sieve_data_type *opt_args,
164 mu_sieve_tag_group_t *tags, int required); 186 mu_sieve_tag_group_t *tags, int required);
165 int mu_sieve_register_action (mu_sieve_machine_t mach, 187 void mu_sieve_register_action (mu_sieve_machine_t mach,
166 const char *name, mu_sieve_handler_t handler, 188 const char *name, mu_sieve_handler_t handler,
167 mu_sieve_data_type *arg_types, 189 mu_sieve_data_type *arg_types,
168 mu_sieve_tag_group_t *tags, int required); 190 mu_sieve_tag_group_t *tags, int required);
169 int mu_sieve_register_comparator (mu_sieve_machine_t mach, const char *name, 191
192 void mu_sieve_register_comparator (mu_sieve_machine_t mach, const char *name,
170 int required, mu_sieve_comparator_t is, 193 int required, mu_sieve_comparator_t is,
171 mu_sieve_comparator_t contains, 194 mu_sieve_comparator_t contains,
172 mu_sieve_comparator_t matches, 195 mu_sieve_comparator_t matches,
173 mu_sieve_comparator_t regex, 196 mu_sieve_comparator_t regex,
174 mu_sieve_comparator_t eq); 197 mu_sieve_comparator_t eq);
175 int mu_sieve_require_action (mu_sieve_machine_t mach, const char *name); 198
176 int mu_sieve_require_test (mu_sieve_machine_t mach, const char *name);
177 int mu_sieve_require_comparator (mu_sieve_machine_t mach, const char *name);
178 int mu_sieve_require_relational (mu_sieve_machine_t mach, const char *name); 199 int mu_sieve_require_relational (mu_sieve_machine_t mach, const char *name);
179 200
180 int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name); 201 void *mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
202 void mu_sieve_unload_ext (void *handle);
203
181 int mu_sieve_match_part_checker (mu_sieve_machine_t mach); 204 int mu_sieve_match_part_checker (mu_sieve_machine_t mach);
182 205
183 mu_sieve_comparator_t mu_sieve_comparator_lookup (mu_sieve_machine_t mach, 206 mu_sieve_comparator_t mu_sieve_comparator_lookup (mu_sieve_machine_t mach,
...@@ -229,7 +252,7 @@ int mu_sieve_vlist_compare (mu_sieve_machine_t mach, ...@@ -229,7 +252,7 @@ int mu_sieve_vlist_compare (mu_sieve_machine_t mach,
229 int mu_sieve_machine_create (mu_sieve_machine_t *mach); 252 int mu_sieve_machine_create (mu_sieve_machine_t *mach);
230 int mu_sieve_machine_dup (mu_sieve_machine_t const in, 253 int mu_sieve_machine_dup (mu_sieve_machine_t const in,
231 mu_sieve_machine_t *out); 254 mu_sieve_machine_t *out);
232 int mu_sieve_machine_inherit (mu_sieve_machine_t const in, 255 int mu_sieve_machine_clone (mu_sieve_machine_t const in,
233 mu_sieve_machine_t *out); 256 mu_sieve_machine_t *out);
234 void mu_sieve_machine_destroy (mu_sieve_machine_t *pmach); 257 void mu_sieve_machine_destroy (mu_sieve_machine_t *pmach);
235 void mu_sieve_machine_add_destructor (mu_sieve_machine_t mach, 258 void mu_sieve_machine_add_destructor (mu_sieve_machine_t mach,
......
...@@ -34,7 +34,7 @@ libmu_sieve_la_SOURCES = \ ...@@ -34,7 +34,7 @@ libmu_sieve_la_SOURCES = \
34 load.c\ 34 load.c\
35 mem.c\ 35 mem.c\
36 prog.c\ 36 prog.c\
37 register.c\ 37 registry.c\
38 relational.c\ 38 relational.c\
39 require.c\ 39 require.c\
40 runtime.c\ 40 runtime.c\
......
...@@ -30,13 +30,7 @@ ...@@ -30,13 +30,7 @@
30 #include <mailutils/cctype.h> 30 #include <mailutils/cctype.h>
31 #include <mailutils/cstr.h> 31 #include <mailutils/cstr.h>
32 32
33 typedef struct { 33 void
34 const char *name;
35 int required;
36 mu_sieve_comparator_t comp[MU_SIEVE_MATCH_LAST];
37 } sieve_comparator_record_t;
38
39 int
40 mu_sieve_register_comparator (mu_sieve_machine_t mach, 34 mu_sieve_register_comparator (mu_sieve_machine_t mach,
41 const char *name, 35 const char *name,
42 int required, 36 int required,
...@@ -46,70 +40,26 @@ mu_sieve_register_comparator (mu_sieve_machine_t mach, ...@@ -46,70 +40,26 @@ mu_sieve_register_comparator (mu_sieve_machine_t mach,
46 mu_sieve_comparator_t regex, 40 mu_sieve_comparator_t regex,
47 mu_sieve_comparator_t eq) 41 mu_sieve_comparator_t eq)
48 { 42 {
49 sieve_comparator_record_t *rp; 43 mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
50 44
51 if (!mach->comp_list) 45 reg->type = mu_sieve_record_comparator;
52 { 46 reg->required = required;
53 int rc = mu_list_create (&mach->comp_list); 47 reg->name = name;
54 if (rc) 48 reg->v.comp[MU_SIEVE_MATCH_IS] = is;
55 return rc; 49 reg->v.comp[MU_SIEVE_MATCH_CONTAINS] = contains;
56 } 50 reg->v.comp[MU_SIEVE_MATCH_MATCHES] = matches;
57 51 reg->v.comp[MU_SIEVE_MATCH_REGEX] = regex;
58 rp = mu_sieve_malloc (mach, sizeof (*rp)); 52 reg->v.comp[MU_SIEVE_MATCH_EQ] = eq;
59 rp->required = required;
60 rp->name = name;
61 rp->comp[MU_SIEVE_MATCH_IS] = is;
62 rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains;
63 rp->comp[MU_SIEVE_MATCH_MATCHES] = matches;
64 rp->comp[MU_SIEVE_MATCH_REGEX] = regex;
65 rp->comp[MU_SIEVE_MATCH_EQ] = eq;
66
67 return mu_list_append (mach->comp_list, rp);
68 }
69
70 sieve_comparator_record_t *
71 _lookup (mu_list_t list, const char *name)
72 {
73 mu_iterator_t itr;
74 sieve_comparator_record_t *reg;
75
76 if (!list || mu_list_get_iterator (list, &itr))
77 return NULL;
78
79 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
80 {
81 mu_iterator_current (itr, (void **)&reg);
82 if (strcmp (reg->name, name) == 0)
83 break;
84 else
85 reg = NULL;
86 }
87 mu_iterator_destroy (&itr);
88 return reg;
89 }
90
91 int
92 mu_sieve_require_comparator (mu_sieve_machine_t mach, const char *name)
93 {
94 sieve_comparator_record_t *reg = _lookup (mach->comp_list, name);
95 if (!reg)
96 {
97 if (!(mu_sieve_load_ext (mach, name) == 0
98 && (reg = _lookup (mach->comp_list, name)) != NULL))
99 return 1;
100 }
101
102 reg->required = 1;
103 return 0;
104 } 53 }
105 54
106 mu_sieve_comparator_t 55 mu_sieve_comparator_t
107 mu_sieve_comparator_lookup (mu_sieve_machine_t mach, const char *name, 56 mu_sieve_comparator_lookup (mu_sieve_machine_t mach, const char *name,
108 int matchtype) 57 int matchtype)
109 { 58 {
110 sieve_comparator_record_t *reg = _lookup (mach->comp_list, name); 59 mu_sieve_registry_t *reg =
111 if (reg && reg->comp[matchtype]) 60 mu_sieve_registry_lookup (mach, name, mu_sieve_record_comparator);
112 return reg->comp[matchtype]; 61 if (reg && reg->v.comp[matchtype])
62 return reg->v.comp[matchtype];
113 return NULL; 63 return NULL;
114 } 64 }
115 65
......
...@@ -272,22 +272,13 @@ static mu_sieve_data_type deleteheader_args[] = { ...@@ -272,22 +272,13 @@ static mu_sieve_data_type deleteheader_args[] = {
272 int 272 int
273 SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach) 273 SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach)
274 { 274 {
275 int rc;
276
277 /* This dummy record is required by libmu_sieve */ 275 /* This dummy record is required by libmu_sieve */
278 rc = mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1); 276 mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1);
279 if (rc) 277 mu_sieve_register_action (mach, "addheader", sieve_addheader,
280 return rc;
281 rc = mu_sieve_register_action (mach, "addheader", sieve_addheader,
282 addheader_args, addheader_tag_groups, 1); 278 addheader_args, addheader_tag_groups, 1);
283 if (rc) 279 mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader,
284 return rc;
285 rc = mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader,
286 deleteheader_args, deleteheader_args, 280 deleteheader_args, deleteheader_args,
287 deleteheader_tag_groups, 281 deleteheader_tag_groups,
288 1); 282 1);
289 if (rc) 283 return 0;
290 return rc;
291
292 return rc;
293 } 284 }
......
...@@ -203,8 +203,9 @@ static mu_sieve_tag_group_t list_tag_groups[] = { ...@@ -203,8 +203,9 @@ static mu_sieve_tag_group_t list_tag_groups[] = {
203 int 203 int
204 SIEVE_EXPORT(list,init) (mu_sieve_machine_t mach) 204 SIEVE_EXPORT(list,init) (mu_sieve_machine_t mach)
205 { 205 {
206 return mu_sieve_register_test (mach, "list", list_test, 206 mu_sieve_register_test (mach, "list", list_test,
207 list_req_args, list_tag_groups, 1); 207 list_req_args, list_tag_groups, 1);
208 return 0;
208 } 209 }
209 210
210 /* End of list.c */ 211 /* End of list.c */
......
...@@ -84,7 +84,7 @@ moderator_filter_message (mu_sieve_machine_t mach, ...@@ -84,7 +84,7 @@ moderator_filter_message (mu_sieve_machine_t mach,
84 84
85 if (mu_sieve_get_tag (mach, "source", SVT_STRING, &arg)) 85 if (mu_sieve_get_tag (mach, "source", SVT_STRING, &arg))
86 { 86 {
87 rc = mu_sieve_machine_inherit (mach, &newmach); 87 rc = mu_sieve_machine_clone (mach, &newmach);
88 if (rc) 88 if (rc)
89 { 89 {
90 mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), 90 mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
...@@ -105,7 +105,7 @@ moderator_filter_message (mu_sieve_machine_t mach, ...@@ -105,7 +105,7 @@ moderator_filter_message (mu_sieve_machine_t mach,
105 { 105 {
106 struct mu_locus locus; 106 struct mu_locus locus;
107 107
108 rc = mu_sieve_machine_inherit (mach, &newmach); 108 rc = mu_sieve_machine_clone (mach, &newmach);
109 if (rc) 109 if (rc)
110 { 110 {
111 mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), 111 mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
...@@ -363,8 +363,9 @@ static mu_sieve_tag_group_t moderator_tag_groups[] = { ...@@ -363,8 +363,9 @@ static mu_sieve_tag_group_t moderator_tag_groups[] = {
363 int 363 int
364 SIEVE_EXPORT(moderator,init) (mu_sieve_machine_t mach) 364 SIEVE_EXPORT(moderator,init) (mu_sieve_machine_t mach)
365 { 365 {
366 return mu_sieve_register_action (mach, "moderator", moderator_action, 366 mu_sieve_register_action (mach, "moderator", moderator_action,
367 moderator_req_args, 367 moderator_req_args,
368 moderator_tag_groups, 1); 368 moderator_tag_groups, 1);
369 return 0;
369 } 370 }
370 371
......
...@@ -275,11 +275,9 @@ static mu_sieve_data_type pipe_args[] = { ...@@ -275,11 +275,9 @@ static mu_sieve_data_type pipe_args[] = {
275 int 275 int
276 SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach) 276 SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach)
277 { 277 {
278 int rc; 278 mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
279 rc = mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
280 pipe_args, pipe_action_tag_groups, 1); 279 pipe_args, pipe_action_tag_groups, 1);
281 if (rc) 280 mu_sieve_register_test (mach, "pipe", sieve_test_pipe,
282 return rc;
283 return mu_sieve_register_test (mach, "pipe", sieve_test_pipe,
284 pipe_args, pipe_test_tag_groups, 1); 281 pipe_args, pipe_test_tag_groups, 1);
282 return 0;
285 } 283 }
......
...@@ -544,7 +544,8 @@ static mu_sieve_tag_group_t spamd_tag_groups[] = { ...@@ -544,7 +544,8 @@ static mu_sieve_tag_group_t spamd_tag_groups[] = {
544 int 544 int
545 SIEVE_EXPORT(spamd,init) (mu_sieve_machine_t mach) 545 SIEVE_EXPORT(spamd,init) (mu_sieve_machine_t mach)
546 { 546 {
547 return mu_sieve_register_test (mach, "spamd", spamd_test, 547 mu_sieve_register_test (mach, "spamd", spamd_test,
548 spamd_req_args, spamd_tag_groups, 1); 548 spamd_req_args, spamd_tag_groups, 1);
549 return 0;
549 } 550 }
550 551
......
...@@ -123,6 +123,7 @@ static mu_sieve_tag_group_t timestamp_tag_groups[] = { ...@@ -123,6 +123,7 @@ static mu_sieve_tag_group_t timestamp_tag_groups[] = {
123 int 123 int
124 SIEVE_EXPORT(timestamp,init) (mu_sieve_machine_t mach) 124 SIEVE_EXPORT(timestamp,init) (mu_sieve_machine_t mach)
125 { 125 {
126 return mu_sieve_register_test (mach, "timestamp", timestamp_test, 126 mu_sieve_register_test (mach, "timestamp", timestamp_test,
127 timestamp_req_args, timestamp_tag_groups, 1); 127 timestamp_req_args, timestamp_tag_groups, 1);
128 return 0;
128 } 129 }
......
...@@ -868,6 +868,7 @@ static mu_sieve_data_type vacation_args[] = { ...@@ -868,6 +868,7 @@ static mu_sieve_data_type vacation_args[] = {
868 868
869 int SIEVE_EXPORT (vacation, init) (mu_sieve_machine_t mach) 869 int SIEVE_EXPORT (vacation, init) (mu_sieve_machine_t mach)
870 { 870 {
871 return mu_sieve_register_action (mach, "vacation", sieve_action_vacation, 871 mu_sieve_register_action (mach, "vacation", sieve_action_vacation,
872 vacation_args, vacation_tag_groups, 1); 872 vacation_args, vacation_tag_groups, 1);
873 return 0;
873 } 874 }
......
...@@ -31,16 +31,6 @@ ...@@ -31,16 +31,6 @@
31 31
32 typedef int (*sieve_module_init_t) (mu_sieve_machine_t mach); 32 typedef int (*sieve_module_init_t) (mu_sieve_machine_t mach);
33 33
34 #if 0
35 /* FIXME: See comment below */
36 static void
37 _free_loaded_module (void *data)
38 {
39 lt_dlclose ((lt_dlhandle)data);
40 lt_dlexit ();
41 }
42 #endif
43
44 static int _add_load_dir (void *, void *); 34 static int _add_load_dir (void *, void *);
45 35
46 static int 36 static int
...@@ -62,7 +52,6 @@ sieve_init_load_path () ...@@ -62,7 +52,6 @@ sieve_init_load_path ()
62 return 0; 52 return 0;
63 } 53 }
64 54
65
66 static lt_dlhandle 55 static lt_dlhandle
67 load_module (mu_sieve_machine_t mach, const char *name) 56 load_module (mu_sieve_machine_t mach, const char *name)
68 { 57 {
...@@ -74,18 +63,12 @@ load_module (mu_sieve_machine_t mach, const char *name) ...@@ -74,18 +63,12 @@ load_module (mu_sieve_machine_t mach, const char *name)
74 handle = lt_dlopenext (name); 63 handle = lt_dlopenext (name);
75 if (handle) 64 if (handle)
76 { 65 {
77 sieve_module_init_t init = (sieve_module_init_t) 66 sieve_module_init_t init;
78 lt_dlsym (handle, "init"); 67
68 init = (sieve_module_init_t) lt_dlsym (handle, "init");
79 if (init) 69 if (init)
80 { 70 {
81 init (mach); 71 init (mach);
82 /* FIXME: We used to have this:
83 mu_sieve_machine_add_destructor (mach, _free_loaded_module,
84 handle);
85 However, unloading modules can lead to random segfaults in
86 case they allocated any global-access data (e.g. mach->msg).
87 In particular, this was the case with extensions/pipe.c.
88 */
89 return handle; 72 return handle;
90 } 73 }
91 else 74 else
...@@ -114,7 +97,7 @@ fix_module_name (char *name) ...@@ -114,7 +97,7 @@ fix_module_name (char *name)
114 } 97 }
115 } 98 }
116 99
117 int 100 void *
118 mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name) 101 mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name)
119 { 102 {
120 lt_dlhandle handle; 103 lt_dlhandle handle;
...@@ -122,11 +105,18 @@ mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name) ...@@ -122,11 +105,18 @@ mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name)
122 105
123 modname = strdup (name); 106 modname = strdup (name);
124 if (!modname) 107 if (!modname)
125 return 1; 108 return NULL;
126 fix_module_name (modname); 109 fix_module_name (modname);
127 handle = load_module (mach, modname); 110 handle = load_module (mach, modname);
128 free (modname); 111 free (modname);
129 return handle == NULL; 112 return handle;
113 }
114
115 void
116 mu_sieve_unload_ext (void *data)
117 {
118 if (data)
119 lt_dlclose ((lt_dlhandle)data);
130 } 120 }
131 121
132 static int 122 static int
......
...@@ -83,6 +83,9 @@ mu_sieve_free (mu_sieve_machine_t mach, void *ptr) ...@@ -83,6 +83,9 @@ mu_sieve_free (mu_sieve_machine_t mach, void *ptr)
83 int rc; 83 int rc;
84 struct memory_cell mcell; 84 struct memory_cell mcell;
85 85
86 if (!ptr)
87 return;
88
86 mcell.ptr = ptr; 89 mcell.ptr = ptr;
87 rc = mu_list_remove (mach->memory_pool, &mcell); 90 rc = mu_list_remove (mach->memory_pool, &mcell);
88 if (rc) 91 if (rc)
...@@ -228,3 +231,65 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb, ...@@ -228,3 +231,65 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb,
228 *pptr = ptr; 231 *pptr = ptr;
229 *pnmemb = nmemb; 232 *pnmemb = nmemb;
230 } 233 }
234
235 char *
236 mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name)
237 {
238 size_t i;
239 char *p;
240
241 if (!name)
242 return NULL;
243
244 for (i = 0; i < mach->idcount; i++)
245 {
246 if (strcmp (mach->idspace[i], name) == 0)
247 return mach->idspace[i];
248 }
249
250 if (mach->idcount == mach->idmax)
251 {
252 mu_i_sv_2nrealloc (mach,
253 (void **) &mach->idspace,
254 &mach->idmax,
255 sizeof mach->idspace[0]);
256 }
257
258 p = mu_sieve_strdup (mach, name);
259 mach->idspace[mach->idcount++] = p;
260
261 return p;
262 }
263
264 size_t
265 mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name)
266 {
267 size_t i;
268
269 for (i = 0; i < mach->idcount; i++)
270 {
271 if (mach->idspace[i] == name || strcmp (mach->idspace[i], name) == 0)
272 return i;
273 }
274 abort ();
275 }
276
277 char *
278 mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n)
279 {
280 if (n >= mach->idcount)
281 abort ();
282 return mach->idspace[n];
283 }
284
285 void
286 mu_i_sv_free_idspace (mu_sieve_machine_t mach)
287 {
288 size_t i;
289
290 for (i = 0; i < mach->idcount; i++)
291 mu_sieve_free (mach, mach->idspace[i]);
292 mach->idcount = 0;
293 }
294
295
......
...@@ -52,7 +52,7 @@ mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr) ...@@ -52,7 +52,7 @@ mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr)
52 if (!file_eq (mach->locus.mu_file, lr->beg.mu_file)) 52 if (!file_eq (mach->locus.mu_file, lr->beg.mu_file))
53 { 53 {
54 mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source); 54 mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source);
55 mu_i_sv_code (mach, (sieve_op_t) lr->beg.mu_file); 55 mu_i_sv_code (mach, (sieve_op_t) mu_i_sv_id_num (mach, lr->beg.mu_file));
56 } 56 }
57 if (mach->locus.mu_line != lr->beg.mu_line) 57 if (mach->locus.mu_line != lr->beg.mu_line)
58 { 58 {
...@@ -133,7 +133,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -133,7 +133,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
133 struct mu_sieve_node *node) 133 struct mu_sieve_node *node)
134 { 134 {
135 size_t i; 135 size_t i;
136 mu_sieve_register_t *reg = node->v.command.reg; 136 mu_sieve_registry_t *reg = node->v.command.reg;
137 137
138 mu_sieve_value_t *start = mach->valspace + node->v.command.argstart; 138 mu_sieve_value_t *start = mach->valspace + node->v.command.argstart;
139 139
...@@ -143,7 +143,10 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -143,7 +143,10 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
143 int rc, err = 0; 143 int rc, err = 0;
144 static mu_sieve_data_type empty[] = { SVT_VOID }; 144 static mu_sieve_data_type empty[] = { SVT_VOID };
145 145
146 exp_arg = reg->req_args ? reg->req_args : empty; 146 if (!reg)
147 return;
148
149 exp_arg = reg->v.command.req_args ? reg->v.command.req_args : empty;
147 150
148 /* Pass 1: consolidation */ 151 /* Pass 1: consolidation */
149 for (i = 0; i < node->v.command.argcount; i++) 152 for (i = 0; i < node->v.command.argcount; i++)
...@@ -153,7 +156,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -153,7 +156,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
153 if (val->type == SVT_TAG) 156 if (val->type == SVT_TAG)
154 { 157 {
155 mu_sieve_tag_checker_t cf; 158 mu_sieve_tag_checker_t cf;
156 mu_sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string, &cf); 159 mu_sieve_tag_def_t *tag = find_tag (reg->v.command.tags,
160 val->v.string, &cf);
157 161
158 if (!tag) 162 if (!tag)
159 { 163 {
...@@ -228,9 +232,9 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -228,9 +232,9 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
228 { 232 {
229 if (*exp_arg == SVT_VOID) 233 if (*exp_arg == SVT_VOID)
230 { 234 {
231 if (reg->opt_args) 235 if (reg->v.command.opt_args)
232 { 236 {
233 exp_arg = reg->opt_args; 237 exp_arg = reg->v.command.opt_args;
234 opt_args = 1; 238 opt_args = 1;
235 } 239 }
236 else 240 else
...@@ -252,7 +256,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -252,7 +256,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
252 { 256 {
253 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 257 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
254 _("type mismatch in argument %lu to `%s'"), 258 _("type mismatch in argument %lu to `%s'"),
255 (unsigned long) (exp_arg - reg->req_args + 1), 259 (unsigned long) (exp_arg - reg->v.command.req_args + 1),
256 reg->name); 260 reg->name);
257 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 261 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
258 _("expected %s but passed %s"), 262 _("expected %s but passed %s"),
...@@ -316,7 +320,7 @@ static void ...@@ -316,7 +320,7 @@ static void
316 sv_code_command (struct mu_sieve_machine *mach, 320 sv_code_command (struct mu_sieve_machine *mach,
317 struct mu_sieve_node *node) 321 struct mu_sieve_node *node)
318 { 322 {
319 mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->handler); 323 mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->v.command.handler);
320 mu_i_sv_code (mach, (sieve_op_t) node->v.command.argstart); 324 mu_i_sv_code (mach, (sieve_op_t) node->v.command.argstart);
321 mu_i_sv_code (mach, (sieve_op_t) node->v.command.argcount); 325 mu_i_sv_code (mach, (sieve_op_t) node->v.command.argcount);
322 mu_i_sv_code (mach, (sieve_op_t) node->v.command.tagcount); 326 mu_i_sv_code (mach, (sieve_op_t) node->v.command.tagcount);
......
...@@ -26,115 +26,116 @@ ...@@ -26,115 +26,116 @@
26 #include <string.h> 26 #include <string.h>
27 #include <sieve-priv.h> 27 #include <sieve-priv.h>
28 28
29 static mu_sieve_register_t * 29 int
30 reg_lookup (mu_list_t list, const char *name) 30 mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name,
31 { 31 enum mu_sieve_record type)
32 mu_iterator_t itr;
33 mu_sieve_register_t *reg;
34
35 if (!list || mu_list_get_iterator (list, &itr))
36 return NULL;
37
38 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
39 {
40 mu_iterator_current (itr, (void **)&reg);
41 if (strcmp (reg->name, name) == 0)
42 break;
43 else
44 reg = NULL;
45 }
46 mu_iterator_destroy (&itr);
47 return reg;
48 }
49
50 mu_sieve_register_t *
51 mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name)
52 {
53 mu_sieve_register_t *reg = reg_lookup (mach->test_list, name);
54 return (reg && reg->handler) ? reg : NULL;
55 }
56
57 mu_sieve_register_t *
58 mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name)
59 { 32 {
60 mu_sieve_register_t *reg = reg_lookup (mach->action_list, name); 33 mu_sieve_registry_t *reg;
61 return (reg && reg->handler) ? reg : NULL;
62 }
63 34
64 static int 35 reg = mu_sieve_registry_lookup (mach, name, type);
65 reg_require (mu_sieve_machine_t mach, mu_list_t list, const char *name)
66 {
67 mu_sieve_register_t *reg = reg_lookup (list, name);
68 if (!reg) 36 if (!reg)
69 { 37 {
70 if (!(mu_sieve_load_ext (mach, name) == 0 38 void *handle = mu_sieve_load_ext (mach, name);
71 && (reg = reg_lookup (list, name)) != NULL)) 39 if (!handle)
40 return 1;
41 reg = mu_sieve_registry_lookup (mach, name, type);
42 if (!reg)
72 return 1; 43 return 1;
44 reg->handle = handle;
73 } 45 }
46
74 reg->required = 1; 47 reg->required = 1;
75 return 0; 48 return 0;
76 } 49 }
77 50
78 int
79 mu_sieve_require_action (mu_sieve_machine_t mach, const char *name)
80 {
81 return reg_require (mach, mach->action_list, name);
82 }
83 51
84 int 52 static void
85 mu_sieve_require_test (mu_sieve_machine_t mach, const char *name) 53 regunload (void *data)
86 { 54 {
87 return reg_require (mach, mach->test_list, name); 55 mu_sieve_registry_t *reg = data;
56 mu_sieve_unload_ext (reg->handle);
88 } 57 }
89 58
90
91 static int 59 static int
92 sieve_register (mu_sieve_machine_t mach, 60 regcmp (void const *a, void const *b)
93 mu_list_t *list,
94 const char *name, mu_sieve_handler_t handler,
95 mu_sieve_data_type *req_arg_types,
96 mu_sieve_data_type *opt_arg_types,
97 mu_sieve_tag_group_t *tags, int required)
98 { 61 {
99 mu_sieve_register_t *reg = mu_sieve_malloc (mach, sizeof (*reg)); 62 mu_sieve_registry_t const *rega = a;
100 63 mu_sieve_registry_t const *regb = b;
101 if (!reg) 64 if (rega->type != regb->type)
102 return ENOMEM; 65 return rega->type - regb->type;
103 reg->name = name; 66 return strcmp (rega->name, regb->name);
104 reg->handler = handler; 67 }
105 68
106 reg->req_args = req_arg_types; 69 mu_sieve_registry_t *
107 reg->opt_args = opt_arg_types; 70 mu_sieve_registry_add (mu_sieve_machine_t mach, const char *name)
108 reg->tags = tags; 71 {
109 reg->required = required; 72 mu_sieve_registry_t *reg;
73 int rc;
110 74
111 if (!*list) 75 if (!mach->registry)
112 { 76 {
113 int rc = mu_list_create (list); 77 rc = mu_list_create (&mach->registry);
114 if (rc) 78 if (rc)
115 { 79 {
116 free (reg); 80 mu_sieve_error (mach, "mu_list_create: %s", mu_strerror (rc));
117 return rc; 81 mu_sieve_abort (mach);
118 } 82 }
83 mu_list_set_destroy_item (mach->registry, regunload);
84 mu_list_set_comparator (mach->registry, regcmp);
119 } 85 }
120 86 reg = mu_sieve_malloc (mach, sizeof (*reg));
121 return mu_list_append (*list, reg); 87 reg->name = name;
88 reg->handle = NULL;
89 reg->required = 0;
90 memset (&reg->v, 0, sizeof reg->v);
91 rc = mu_list_append (mach->registry, reg);
92 if (rc)
93 {
94 mu_sieve_error (mach, "mu_list_append: %s", mu_strerror (rc));
95 mu_sieve_abort (mach);
96 }
97 return reg;
122 } 98 }
123 99
100 mu_sieve_registry_t *
101 mu_sieve_registry_lookup (mu_sieve_machine_t mach, const char *name,
102 enum mu_sieve_record type)
103 {
104 mu_sieve_registry_t key, *reg;
105 int rc;
124 106
125 int 107 key.name = name;
108 key.type = type;
109
110 rc = mu_list_locate (mach->registry, &key, (void**) &reg);
111 if (rc == MU_ERR_NOENT)
112 return NULL;
113 else if (rc)
114 {
115 mu_sieve_error (mach, _("registry lookup failed: %s"), mu_strerror (rc));
116 mu_sieve_abort (mach);
117 }
118 return reg;
119 }
120
121 void
126 mu_sieve_register_test_ext (mu_sieve_machine_t mach, 122 mu_sieve_register_test_ext (mu_sieve_machine_t mach,
127 const char *name, mu_sieve_handler_t handler, 123 const char *name, mu_sieve_handler_t handler,
128 mu_sieve_data_type *req_args, 124 mu_sieve_data_type *req_args,
129 mu_sieve_data_type *opt_args, 125 mu_sieve_data_type *opt_args,
130 mu_sieve_tag_group_t *tags, int required) 126 mu_sieve_tag_group_t *tags, int required)
131 { 127 {
132 return sieve_register (mach, 128 mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
133 &mach->test_list, name, handler, 129
134 req_args, opt_args, tags, required); 130 reg->type = mu_sieve_record_test;
131 reg->required = required;
132 reg->v.command.handler = handler;
133 reg->v.command.req_args = req_args;
134 reg->v.command.opt_args = opt_args;
135 reg->v.command.tags = tags;
135 } 136 }
136 137
137 int 138 void
138 mu_sieve_register_test (mu_sieve_machine_t mach, 139 mu_sieve_register_test (mu_sieve_machine_t mach,
139 const char *name, mu_sieve_handler_t handler, 140 const char *name, mu_sieve_handler_t handler,
140 mu_sieve_data_type *arg_types, 141 mu_sieve_data_type *arg_types,
...@@ -146,19 +147,24 @@ mu_sieve_register_test (mu_sieve_machine_t mach, ...@@ -146,19 +147,24 @@ mu_sieve_register_test (mu_sieve_machine_t mach,
146 required); 147 required);
147 } 148 }
148 149
149 int 150 void
150 mu_sieve_register_action_ext (mu_sieve_machine_t mach, 151 mu_sieve_register_action_ext (mu_sieve_machine_t mach,
151 const char *name, mu_sieve_handler_t handler, 152 const char *name, mu_sieve_handler_t handler,
152 mu_sieve_data_type *req_args, 153 mu_sieve_data_type *req_args,
153 mu_sieve_data_type *opt_args, 154 mu_sieve_data_type *opt_args,
154 mu_sieve_tag_group_t *tags, int required) 155 mu_sieve_tag_group_t *tags, int required)
155 { 156 {
156 return sieve_register (mach, 157 mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
157 &mach->action_list, name, handler, 158
158 req_args, opt_args, tags, required); 159 reg->type = mu_sieve_record_action;
160 reg->required = required;
161 reg->v.command.handler = handler;
162 reg->v.command.req_args = req_args;
163 reg->v.command.opt_args = opt_args;
164 reg->v.command.tags = tags;
159 } 165 }
160 166
161 int 167 void
162 mu_sieve_register_action (mu_sieve_machine_t mach, 168 mu_sieve_register_action (mu_sieve_machine_t mach,
163 const char *name, mu_sieve_handler_t handler, 169 const char *name, mu_sieve_handler_t handler,
164 mu_sieve_data_type *arg_types, 170 mu_sieve_data_type *arg_types,
......
...@@ -35,42 +35,26 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list) ...@@ -35,42 +35,26 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list)
35 { 35 {
36 struct mu_sieve_string *str = mu_sieve_string_raw (mach, list, i); 36 struct mu_sieve_string *str = mu_sieve_string_raw (mach, list, i);
37 char *name = str->orig; 37 char *name = str->orig;
38 int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL; 38 int rc;
39 const char *text = NULL;
40 39
41 if (strncmp (name, "comparator-", 11) == 0) 40 if (strcmp (name, "relational") == 0) /* RFC 3431 */
42 { 41 rc = mu_sieve_require_relational (mach, name);
43 name += 11;
44 reqfn = mu_sieve_require_comparator;
45 text = _("required comparator");
46 }
47 else if (strncmp (name, "test-", 5) == 0) /* GNU extension */
48 {
49 name += 5;
50 reqfn = mu_sieve_require_test;
51 text = _("required test");
52 }
53 else if (strcmp (name, "relational") == 0) /* RFC 3431 */
54 {
55 reqfn = mu_sieve_require_relational;
56 text = "";
57 }
58 else if (strcmp (name, "encoded-character") == 0) /* RFC 5228, 2.4.2.4 */ 42 else if (strcmp (name, "encoded-character") == 0) /* RFC 5228, 2.4.2.4 */
59 { 43 rc = mu_sieve_require_encoded_character (mach, name);
60 reqfn = mu_sieve_require_encoded_character; 44 else if (strncmp (name, "comparator-", 11) == 0)
61 text = ""; 45 rc = mu_sieve_registry_require (mach, name + 11,
62 } 46 mu_sieve_record_comparator);
47 else if (strncmp (name, "test-", 5) == 0) /* GNU extension */
48 rc = mu_sieve_registry_require (mach, name + 5,
49 mu_sieve_record_test);
63 else 50 else
64 { 51 rc = mu_sieve_registry_require (mach, name, mu_sieve_record_action);
65 reqfn = mu_sieve_require_action;
66 text = _("required action");
67 }
68 52
69 if (reqfn (mach, name)) 53 if (rc)
70 { 54 {
71 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 55 mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
72 _("source for the %s %s is not available"), 56 _("can't require %s is not available"),
73 text, name); 57 name);
74 mu_i_sv_error (mach); 58 mu_i_sv_error (mach);
75 } 59 }
76 } 60 }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
34 void 34 void
35 _mu_i_sv_instr_source (mu_sieve_machine_t mach) 35 _mu_i_sv_instr_source (mu_sieve_machine_t mach)
36 { 36 {
37 mach->locus.mu_file = (char*) SIEVE_RT_ARG (mach, 0, string); 37 mach->locus.mu_file = mu_i_sv_id_str (mach, SIEVE_RT_ARG (mach, 0, pc));
38 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, 38 mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
39 MU_IOCTL_LOGSTREAM_SET_LOCUS, 39 MU_IOCTL_LOGSTREAM_SET_LOCUS,
40 &mach->locus); 40 &mach->locus);
...@@ -98,38 +98,6 @@ _mu_i_sv_instr_test (mu_sieve_machine_t mach) ...@@ -98,38 +98,6 @@ _mu_i_sv_instr_test (mu_sieve_machine_t mach)
98 } 98 }
99 99
100 void 100 void
101 _mu_i_sv_instr_push (mu_sieve_machine_t mach)
102 {
103 if (INSTR_DEBUG (mach))
104 mu_i_sv_debug (mach, mach->pc - 1, "PUSH");
105 if (INSTR_DISASS (mach))
106 return;
107
108 if (!mach->stack && mu_list_create (&mach->stack))
109 {
110 mu_sieve_error (mach, _("cannot create stack"));
111 mu_sieve_abort (mach);
112 }
113 mu_list_push (mach->stack, (void*) mach->reg);
114 }
115
116 void
117 _mu_i_sv_instr_pop (mu_sieve_machine_t mach)
118 {
119 if (INSTR_DEBUG (mach))
120 mu_i_sv_debug (mach, mach->pc - 1, "POP");
121 if (INSTR_DISASS (mach))
122 return;
123
124 if (!mach->stack || mu_list_is_empty (mach->stack))
125 {
126 mu_sieve_error (mach, _("stack underflow"));
127 mu_sieve_abort (mach);
128 }
129 mu_list_pop (mach->stack, (void **)&mach->reg);
130 }
131
132 void
133 _mu_i_sv_instr_not (mu_sieve_machine_t mach) 101 _mu_i_sv_instr_not (mu_sieve_machine_t mach)
134 { 102 {
135 if (INSTR_DEBUG (mach)) 103 if (INSTR_DEBUG (mach))
...@@ -207,7 +175,7 @@ mu_sieve_get_data (mu_sieve_machine_t mach) ...@@ -207,7 +175,7 @@ mu_sieve_get_data (mu_sieve_machine_t mach)
207 int 175 int
208 mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus *loc) 176 mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus *loc)
209 { 177 {
210 if (mach->source_list) 178 if (mach->locus.mu_file)
211 { 179 {
212 *loc = mach->locus; 180 *loc = mach->locus;
213 return 0; 181 return 0;
......
...@@ -68,10 +68,11 @@ struct mu_sieve_machine ...@@ -68,10 +68,11 @@ struct mu_sieve_machine
68 68
69 /* Symbol space: */ 69 /* Symbol space: */
70 mu_opool_t string_pool; /* String constants */ 70 mu_opool_t string_pool; /* String constants */
71 mu_list_t source_list; /* Source names (for diagnostics) */ 71 mu_list_t registry; /* Tests, Actions, Comparators */
72 mu_list_t test_list; /* Tests */ 72
73 mu_list_t action_list; /* Actions */ 73 char **idspace; /* Source and identifier names */
74 mu_list_t comp_list; /* Comparators */ 74 size_t idcount;
75 size_t idmax;
75 76
76 mu_sieve_string_t *stringspace; 77 mu_sieve_string_t *stringspace;
77 size_t stringcount; 78 size_t stringcount;
...@@ -88,7 +89,6 @@ struct mu_sieve_machine ...@@ -88,7 +89,6 @@ struct mu_sieve_machine
88 enum mu_sieve_state state; /* Machine state */ 89 enum mu_sieve_state state; /* Machine state */
89 size_t pc; /* Current program counter */ 90 size_t pc; /* Current program counter */
90 long reg; /* Numeric register */ 91 long reg; /* Numeric register */
91 mu_list_t stack; /* Runtime stack */
92 92
93 /* Call environment */ 93 /* Call environment */
94 const char *identifier; /* Name of action or test being executed */ 94 const char *identifier; /* Name of action or test being executed */
...@@ -152,7 +152,7 @@ struct mu_sieve_node ...@@ -152,7 +152,7 @@ struct mu_sieve_node
152 } cond; 152 } cond;
153 struct 153 struct
154 { 154 {
155 mu_sieve_register_t *reg; 155 mu_sieve_registry_t *reg;
156 size_t argstart; 156 size_t argstart;
157 size_t argcount; 157 size_t argcount;
158 size_t tagcount; 158 size_t tagcount;
...@@ -167,7 +167,7 @@ int mu_sieve_yylex (void); ...@@ -167,7 +167,7 @@ int mu_sieve_yylex (void);
167 int mu_i_sv_lex_begin (const char *name); 167 int mu_i_sv_lex_begin (const char *name);
168 int mu_i_sv_lex_begin_string (const char *buf, int bufsize, 168 int mu_i_sv_lex_begin_string (const char *buf, int bufsize,
169 const char *fname, int line); 169 const char *fname, int line);
170 void mu_i_sv_lex_finish (struct mu_sieve_machine *mach); 170 void mu_i_sv_lex_finish (void);
171 171
172 extern mu_sieve_machine_t mu_sieve_machine; 172 extern mu_sieve_machine_t mu_sieve_machine;
173 173
...@@ -182,8 +182,6 @@ void mu_i_sv_code_test (struct mu_sieve_machine *mach, ...@@ -182,8 +182,6 @@ void mu_i_sv_code_test (struct mu_sieve_machine *mach,
182 /* Opcodes */ 182 /* Opcodes */
183 void _mu_i_sv_instr_action (mu_sieve_machine_t mach); 183 void _mu_i_sv_instr_action (mu_sieve_machine_t mach);
184 void _mu_i_sv_instr_test (mu_sieve_machine_t mach); 184 void _mu_i_sv_instr_test (mu_sieve_machine_t mach);
185 void _mu_i_sv_instr_push (mu_sieve_machine_t mach);
186 void _mu_i_sv_instr_pop (mu_sieve_machine_t mach);
187 void _mu_i_sv_instr_not (mu_sieve_machine_t mach); 185 void _mu_i_sv_instr_not (mu_sieve_machine_t mach);
188 void _mu_i_sv_instr_branch (mu_sieve_machine_t mach); 186 void _mu_i_sv_instr_branch (mu_sieve_machine_t mach);
189 void _mu_i_sv_instr_brz (mu_sieve_machine_t mach); 187 void _mu_i_sv_instr_brz (mu_sieve_machine_t mach);
...@@ -230,3 +228,9 @@ void mu_i_sv_lint_command (struct mu_sieve_machine *mach, ...@@ -230,3 +228,9 @@ void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
230 228
231 size_t mu_i_sv_string_create (mu_sieve_machine_t mach, char *str); 229 size_t mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
232 230
231 char *mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name);
232 size_t mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name);
233 char *mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n);
234 void mu_i_sv_free_idspace (mu_sieve_machine_t mach);
235
236
......
...@@ -56,7 +56,6 @@ static int isemptystr (char *text); ...@@ -56,7 +56,6 @@ static int isemptystr (char *text);
56 static ino_t sieve_source_inode; 56 static ino_t sieve_source_inode;
57 struct mu_locus mu_sieve_locus; 57 struct mu_locus mu_sieve_locus;
58 static int newline; 58 static int newline;
59 static mu_list_t file_names;
60 59
61 static mu_stream_t input_stream; 60 static mu_stream_t input_stream;
62 61
...@@ -90,35 +89,10 @@ fillbuf (char *buf, size_t max_size) ...@@ -90,35 +89,10 @@ fillbuf (char *buf, size_t max_size)
90 yy_switch_to_buffer (s); \ 89 yy_switch_to_buffer (s); \
91 } while (0) 90 } while (0)
92 91
93 static int
94 file_name_cmp (const void *a, const void *b)
95 {
96 return strcmp (a, b);
97 }
98
99 static void 92 static void
100 init_locus (char const *name, ino_t ino) 93 init_locus (char const *name, ino_t ino)
101 { 94 {
102 mu_sieve_locus.mu_file = NULL; 95 mu_sieve_locus.mu_file = mu_i_sv_id_canon (mu_sieve_machine, name);
103 if (name)
104 {
105 if (!file_names)
106 {
107 mu_list_create (&file_names);
108 mu_list_set_comparator (file_names, file_name_cmp);
109 mu_list_set_destroy_item (file_names, mu_list_free_item);
110 }
111 else
112 {
113 mu_list_locate (file_names, (void*) name,
114 (void**) &mu_sieve_locus.mu_file);
115 }
116 if (!mu_sieve_locus.mu_file)
117 {
118 mu_sieve_locus.mu_file = strdup (name);//FIXME: Error checking
119 mu_list_append (file_names, mu_sieve_locus.mu_file);
120 }
121 }
122 mu_sieve_locus.mu_line = 1; 96 mu_sieve_locus.mu_line = 1;
123 mu_sieve_locus.mu_col = 0; 97 mu_sieve_locus.mu_col = 0;
124 newline = 0; 98 newline = 0;
...@@ -496,12 +470,10 @@ mu_i_sv_lex_begin_string (const char *buf, int bufsize, ...@@ -496,12 +470,10 @@ mu_i_sv_lex_begin_string (const char *buf, int bufsize,
496 } 470 }
497 471
498 void 472 void
499 mu_i_sv_lex_finish (struct mu_sieve_machine *mach) 473 mu_i_sv_lex_finish (void)
500 { 474 {
501 while (pop_source () == 0) 475 while (pop_source () == 0)
502 ; 476 ;
503 mach->source_list = file_names;
504 file_names = NULL;
505 } 477 }
506 478
507 static int 479 static int
......
...@@ -245,10 +245,11 @@ cond : test ...@@ -245,10 +245,11 @@ cond : test
245 245
246 test : command 246 test : command
247 { 247 {
248 mu_sieve_register_t *reg; 248 mu_sieve_registry_t *reg;
249 249
250 mu_sieve_machine->locus = @1.beg; 250 mu_sieve_machine->locus = @1.beg;
251 reg = mu_sieve_test_lookup (mu_sieve_machine, $1.ident); 251 reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
252 mu_sieve_record_test);
252 if (!reg) 253 if (!reg)
253 { 254 {
254 mu_diag_at_locus (MU_LOG_ERROR, &@1.beg, 255 mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
...@@ -292,10 +293,11 @@ command : IDENT maybe_arglist ...@@ -292,10 +293,11 @@ command : IDENT maybe_arglist
292 293
293 action : command 294 action : command
294 { 295 {
295 mu_sieve_register_t *reg; 296 mu_sieve_registry_t *reg;
296 297
297 mu_sieve_machine->locus = @1.beg; 298 mu_sieve_machine->locus = @1.beg;
298 reg = mu_sieve_action_lookup (mu_sieve_machine, $1.ident); 299 reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
300 mu_sieve_record_action);
299 301
300 if (!reg) 302 if (!reg)
301 { 303 {
...@@ -999,8 +1001,6 @@ mu_sieve_machine_create (mu_sieve_machine_t *pmach) ...@@ -999,8 +1001,6 @@ mu_sieve_machine_create (mu_sieve_machine_t *pmach)
999 return rc; 1001 return rc;
1000 } 1002 }
1001 1003
1002 mach->source_list = NULL;
1003
1004 mach->data = NULL; 1004 mach->data = NULL;
1005 1005
1006 mu_sieve_set_diag_stream (mach, mu_strerr); 1006 mu_sieve_set_diag_stream (mach, mu_strerr);
...@@ -1053,10 +1053,8 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach) ...@@ -1053,10 +1053,8 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach)
1053 mu_list_clear (mach->memory_pool); 1053 mu_list_clear (mach->memory_pool);
1054 mu_list_clear (mach->destr_list); 1054 mu_list_clear (mach->destr_list);
1055 mu_opool_free (mach->string_pool, NULL); 1055 mu_opool_free (mach->string_pool, NULL);
1056 mu_list_clear (mach->source_list); 1056 mu_i_sv_free_idspace (mach);
1057 mu_list_clear (mach->test_list); 1057 mu_list_clear (mach->registry);
1058 mu_list_clear (mach->action_list);
1059 mu_list_clear (mach->comp_list);
1060 1058
1061 mach->stringspace = NULL; 1059 mach->stringspace = NULL;
1062 mach->stringcount = 0; 1060 mach->stringcount = 0;
...@@ -1074,22 +1072,19 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach) ...@@ -1074,22 +1072,19 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach)
1074 return 0; 1072 return 0;
1075 } 1073 }
1076 1074
1077 int 1075 static int
1078 mu_sieve_machine_inherit (mu_sieve_machine_t const parent, 1076 regdup (void *item, void *data)
1079 mu_sieve_machine_t *pmach)
1080 { 1077 {
1081 mu_sieve_machine_t child; 1078 mu_sieve_registry_t *reg = item;
1082 int rc; 1079 mu_sieve_machine_t mach = data;
1083
1084 if (!parent || parent->state == mu_sieve_state_error)
1085 return EINVAL;
1086 1080
1087 rc = mu_sieve_machine_create (&child); 1081 mu_sieve_registry_require (mach, reg->name, reg->type);
1088 if (rc) 1082 return 0;
1089 return rc; 1083 }
1090
1091 child->dry_run = parent->dry_run;
1092 1084
1085 static void
1086 copy_stream_state (mu_sieve_machine_t child, mu_sieve_machine_t parent)
1087 {
1093 child->state_flags = parent->state_flags; 1088 child->state_flags = parent->state_flags;
1094 child->err_mode = parent->err_mode; 1089 child->err_mode = parent->err_mode;
1095 child->err_locus = parent->err_locus; 1090 child->err_locus = parent->err_locus;
...@@ -1105,13 +1100,97 @@ mu_sieve_machine_inherit (mu_sieve_machine_t const parent, ...@@ -1105,13 +1100,97 @@ mu_sieve_machine_inherit (mu_sieve_machine_t const parent,
1105 mu_stream_ref (child->errstream); 1100 mu_stream_ref (child->errstream);
1106 child->dbgstream = parent->dbgstream; 1101 child->dbgstream = parent->dbgstream;
1107 mu_stream_ref (child->dbgstream); 1102 mu_stream_ref (child->dbgstream);
1103 }
1104
1105 int
1106 mu_sieve_machine_clone (mu_sieve_machine_t const parent,
1107 mu_sieve_machine_t *pmach)
1108 {
1109 size_t i;
1110 mu_sieve_machine_t child;
1111 int rc;
1112
1113 if (!parent || parent->state == mu_sieve_state_error)
1114 return EINVAL;
1115
1116 rc = mu_sieve_machine_create (&child);
1117 if (rc)
1118 return rc;
1119
1120 rc = setjmp (child->errbuf);
1121
1122 if (rc == 0)
1123 {
1124 child->state = mu_sieve_state_init;
1125 mu_i_sv_register_standard_actions (child);
1126 mu_i_sv_register_standard_tests (child);
1127 mu_i_sv_register_standard_comparators (child);
1128
1129 /* Load necessary modules */
1130 mu_list_foreach (parent->registry, regdup, child);
1131
1132 /* Copy identifiers */
1133 child->idspace = mu_sieve_calloc (child, parent->idcount,
1134 sizeof (child->idspace[0]));
1135 child->idcount = child->idmax = parent->idcount;
1136 for (i = 0; i < child->idcount; i++)
1137 child->idspace[i] = mu_sieve_strdup (parent, parent->idspace[i]);
1138
1139 /* Copy string constants */
1140 child->stringspace = mu_sieve_calloc (child, parent->stringcount,
1141 sizeof (child->stringspace[0]));
1142 child->stringcount = child->stringmax = parent->stringcount;
1143 for (i = 0; i < parent->stringcount; i++)
1144 {
1145 memset (&child->stringspace[i], 0, sizeof (child->stringspace[0]));
1146 child->stringspace[i].orig =
1147 mu_sieve_strdup (parent, parent->stringspace[i].orig);
1148 }
1149
1150 /* Copy value space */
1151 child->valspace = mu_sieve_calloc (parent, parent->valcount,
1152 sizeof child->valspace[0]);
1153 child->valcount = child->valmax = parent->valcount;
1154 for (i = 0; i < child->valcount; i++)
1155 {
1156 child->valspace[i].type = parent->valspace[i].type;
1157 child->valspace[i].tag =
1158 mu_sieve_strdup (parent, parent->valspace[i].tag);
1159 switch (child->valspace[i].type)
1160 {
1161 case SVT_TAG:
1162 child->valspace[i].v.string =
1163 mu_sieve_strdup (parent, parent->valspace[i].v.string);
1164 break;
1165
1166 default:
1167 child->valspace[i].v = parent->valspace[i].v;
1168 }
1169 }
1170
1171 /* Copy progspace */
1172 child->progsize = parent->progsize;
1173 child->prog = mu_sieve_calloc (child, parent->progsize,
1174 sizeof child->prog[0]);
1175 memcpy (child->prog, parent->prog,
1176 parent->progsize * sizeof (child->prog[0]));
1177
1178 /* Copy user-defined settings */
1179
1180 child->dry_run = parent->dry_run;
1181
1182 copy_stream_state (child, parent);
1108 1183
1109 child->data = parent->data; 1184 child->data = parent->data;
1110 child->logger = parent->logger; 1185 child->logger = parent->logger;
1111 child->daemon_email = parent->daemon_email; 1186 child->daemon_email = parent->daemon_email;
1112 1187
1113 *pmach = child; 1188 *pmach = child;
1114 return 0; 1189 }
1190 else
1191 mu_sieve_machine_destroy (&child);
1192
1193 return rc;
1115 } 1194 }
1116 1195
1117 int 1196 int
...@@ -1133,9 +1212,7 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) ...@@ -1133,9 +1212,7 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out)
1133 return rc; 1212 return rc;
1134 } 1213 }
1135 mach->destr_list = NULL; 1214 mach->destr_list = NULL;
1136 mach->test_list = NULL; 1215 mach->registry = NULL;
1137 mach->action_list = NULL;
1138 mach->comp_list = NULL;
1139 1216
1140 mach->progsize = in->progsize; 1217 mach->progsize = in->progsize;
1141 mach->prog = in->prog; 1218 mach->prog = in->prog;
...@@ -1151,9 +1228,12 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) ...@@ -1151,9 +1228,12 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out)
1151 mach->state = in->state; 1228 mach->state = in->state;
1152 } 1229 }
1153 1230
1231 rc = setjmp (mach->errbuf);
1232
1233 if (rc == 0)
1234 {
1154 mach->pc = 0; 1235 mach->pc = 0;
1155 mach->reg = 0; 1236 mach->reg = 0;
1156 mach->stack = NULL;
1157 1237
1158 mach->dry_run = in->dry_run; 1238 mach->dry_run = in->dry_run;
1159 1239
...@@ -1163,17 +1243,18 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) ...@@ -1163,17 +1243,18 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out)
1163 mach->dbg_mode = in->dbg_mode; 1243 mach->dbg_mode = in->dbg_mode;
1164 mach->dbg_locus = in->dbg_locus; 1244 mach->dbg_locus = in->dbg_locus;
1165 1245
1166 mach->errstream = in->errstream; 1246 copy_stream_state (mach, in);
1167 mu_stream_ref (mach->errstream);
1168 mach->dbgstream = in->dbgstream;
1169 mu_stream_ref (mach->dbgstream);
1170 1247
1171 mach->data = in->data; 1248 mach->data = in->data;
1172 mach->logger = in->logger; 1249 mach->logger = in->logger;
1173 mach->daemon_email = in->daemon_email; 1250 mach->daemon_email = in->daemon_email;
1174 1251
1175 *out = mach; 1252 *out = mach;
1176 return 0; 1253 }
1254 else
1255 mu_sieve_machine_destroy (&mach);
1256
1257 return rc;
1177 } 1258 }
1178 1259
1179 void 1260 void
...@@ -1334,14 +1415,13 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach) ...@@ -1334,14 +1415,13 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
1334 mu_sieve_machine_t mach = *pmach; 1415 mu_sieve_machine_t mach = *pmach;
1335 1416
1336 mu_i_sv_free_stringspace (mach); 1417 mu_i_sv_free_stringspace (mach);
1418 mu_sieve_free (mach, mach->stringspace);
1337 mu_stream_destroy (&mach->errstream); 1419 mu_stream_destroy (&mach->errstream);
1338 mu_stream_destroy (&mach->dbgstream); 1420 mu_stream_destroy (&mach->dbgstream);
1339 mu_mailer_destroy (&mach->mailer); 1421 mu_mailer_destroy (&mach->mailer);
1340 mu_list_destroy (&mach->destr_list); 1422 mu_list_destroy (&mach->destr_list);
1341 mu_list_destroy (&mach->action_list); 1423 mu_list_destroy (&mach->registry);
1342 mu_list_destroy (&mach->test_list); 1424 mu_sieve_free (mach, mach->idspace);
1343 mu_list_destroy (&mach->comp_list);
1344 mu_list_destroy (&mach->source_list);
1345 mu_opool_destroy (&mach->string_pool); 1425 mu_opool_destroy (&mach->string_pool);
1346 mu_list_destroy (&mach->memory_pool); 1426 mu_list_destroy (&mach->memory_pool);
1347 free (mach); 1427 free (mach);
...@@ -1397,7 +1477,7 @@ sieve_parse (void) ...@@ -1397,7 +1477,7 @@ sieve_parse (void)
1397 yydebug = mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE3); 1477 yydebug = mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE3);
1398 1478
1399 rc = yyparse (); 1479 rc = yyparse ();
1400 mu_i_sv_lex_finish (mu_sieve_machine); 1480 mu_i_sv_lex_finish ();
1401 if (rc) 1481 if (rc)
1402 mu_i_sv_error (mu_sieve_machine); 1482 mu_i_sv_error (mu_sieve_machine);
1403 if (mu_sieve_machine->state == mu_sieve_state_init) 1483 if (mu_sieve_machine->state == mu_sieve_state_init)
......