sieve: provide a separate stream for debugging output
* include/mailutils/sieve.h (MU_SIEVE_DEBUG_TRACE) (MU_SIEVE_DEBUG_INSTR,MU_SIEVE_DEBUG_DISAS) (MU_SIEVE_DRY_RUN): Remove. (mu_sieve_machine_init_ex): Remove proto. (mu_sieve_set_dbg_stream,mu_sieve_get_dbg_stream) (mu_sieve_stream_save) (mu_sieve_stream_restore): New protos. * libmu_sieve/runtime.c (INSTR_DISASS,INSTR_DEBUG): Reimplement. * libmu_sieve/sieve-priv.h (MU_SV_SAVED_ERR_STATE) (MU_SV_SAVED_DBG_STATE,MU_SV_SAVED_STATE): New bitflags. (mu_sieve_state_disass): New constant. (mu_sieve_machine)<state_flags, err_mode> <err_locus,dbg_mode,dbg_locus>: New members. <dbgstream>: New member. * libmu_sieve/sieve.y (mu_sieve_machine_init_ex): Remove. (mu_sieve_machine_dup, mu_sieve_machine_inherit): Fix. (mu_sieve_set_dbg_stream) (mu_sieve_get_dbg_stream): New functions. (mu_sieve_machine_destroy): Destroy dbgstream. (with_machine): Preserve stream state (mode & locus). * libmu_sieve/util.c (mu_i_sv_debug,mu_i_sv_debug_command): Use ioctl instead of format strings. (mu_sieve_stream_save, mu_sieve_stream_restore): New functions. * python/libmu_py/sieve.c (api_sieve_machine_init): Use mu_sieve_machine_init. * sieve/sieve.c: Improve help output. (main): Dump disassembled code to standard output.
Showing
8 changed files
with
250 additions
and
135 deletions
... | @@ -116,12 +116,6 @@ typedef struct | ... | @@ -116,12 +116,6 @@ typedef struct |
116 | #define MU_SIEVE_MATCH_EQ 5 | 116 | #define MU_SIEVE_MATCH_EQ 5 |
117 | #define MU_SIEVE_MATCH_LAST 6 | 117 | #define MU_SIEVE_MATCH_LAST 6 |
118 | 118 | ||
119 | /* Debugging levels */ | ||
120 | #define MU_SIEVE_DEBUG_TRACE 0x0001 | ||
121 | #define MU_SIEVE_DEBUG_INSTR 0x0002 | ||
122 | #define MU_SIEVE_DEBUG_DISAS 0x0004 | ||
123 | #define MU_SIEVE_DRY_RUN 0x0008 | ||
124 | |||
125 | extern mu_debug_handle_t mu_sieve_debug_handle; | 119 | extern mu_debug_handle_t mu_sieve_debug_handle; |
126 | extern mu_list_t mu_sieve_include_path; | 120 | extern mu_list_t mu_sieve_include_path; |
127 | extern mu_list_t mu_sieve_library_path; | 121 | extern mu_list_t mu_sieve_library_path; |
... | @@ -212,9 +206,6 @@ int mu_sieve_vlist_compare (mu_sieve_value_t * a, mu_sieve_value_t * b, | ... | @@ -212,9 +206,6 @@ int mu_sieve_vlist_compare (mu_sieve_value_t * a, mu_sieve_value_t * b, |
212 | 206 | ||
213 | /* Functions to create and destroy sieve machine */ | 207 | /* Functions to create and destroy sieve machine */ |
214 | int mu_sieve_machine_init (mu_sieve_machine_t *mach); | 208 | int mu_sieve_machine_init (mu_sieve_machine_t *mach); |
215 | int mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach, | ||
216 | void *data, | ||
217 | mu_stream_t errstream); | ||
218 | int mu_sieve_machine_dup (mu_sieve_machine_t const in, | 209 | int mu_sieve_machine_dup (mu_sieve_machine_t const in, |
219 | mu_sieve_machine_t *out); | 210 | mu_sieve_machine_t *out); |
220 | int mu_sieve_machine_inherit (mu_sieve_machine_t const in, | 211 | int mu_sieve_machine_inherit (mu_sieve_machine_t const in, |
... | @@ -227,6 +218,9 @@ int mu_sieve_machine_add_destructor (mu_sieve_machine_t mach, | ... | @@ -227,6 +218,9 @@ int mu_sieve_machine_add_destructor (mu_sieve_machine_t mach, |
227 | void mu_sieve_get_diag_stream (mu_sieve_machine_t mach, mu_stream_t *pstr); | 218 | void mu_sieve_get_diag_stream (mu_sieve_machine_t mach, mu_stream_t *pstr); |
228 | void mu_sieve_set_diag_stream (mu_sieve_machine_t mach, mu_stream_t str); | 219 | void mu_sieve_set_diag_stream (mu_sieve_machine_t mach, mu_stream_t str); |
229 | 220 | ||
221 | void mu_sieve_set_dbg_stream (mu_sieve_machine_t mach, mu_stream_t str); | ||
222 | void mu_sieve_get_dbg_stream (mu_sieve_machine_t mach, mu_stream_t *pstr); | ||
223 | |||
230 | void *mu_sieve_get_data (mu_sieve_machine_t mach); | 224 | void *mu_sieve_get_data (mu_sieve_machine_t mach); |
231 | void mu_sieve_set_data (mu_sieve_machine_t mach, void *); | 225 | void mu_sieve_set_data (mu_sieve_machine_t mach, void *); |
232 | mu_message_t mu_sieve_get_message (mu_sieve_machine_t mach); | 226 | mu_message_t mu_sieve_get_message (mu_sieve_machine_t mach); |
... | @@ -247,6 +241,10 @@ void mu_sieve_set_daemon_email (mu_sieve_machine_t mach, const char *email); | ... | @@ -247,6 +241,10 @@ void mu_sieve_set_daemon_email (mu_sieve_machine_t mach, const char *email); |
247 | 241 | ||
248 | int mu_sieve_get_message_sender (mu_message_t msg, char **ptext); | 242 | int mu_sieve_get_message_sender (mu_message_t msg, char **ptext); |
249 | 243 | ||
244 | /* Stream state saving & restoring */ | ||
245 | void mu_sieve_stream_save (mu_sieve_machine_t mach); | ||
246 | void mu_sieve_stream_restore (mu_sieve_machine_t mach); | ||
247 | |||
250 | /* Logging and diagnostic functions */ | 248 | /* Logging and diagnostic functions */ |
251 | 249 | ||
252 | void mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...) | 250 | void mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...) | ... | ... |
... | @@ -27,10 +27,9 @@ | ... | @@ -27,10 +27,9 @@ |
27 | #define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t) | 27 | #define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t) |
28 | #define SIEVE_ADJUST(m,n) (m)->pc+=(n) | 28 | #define SIEVE_ADJUST(m,n) (m)->pc+=(n) |
29 | 29 | ||
30 | #define INSTR_DISASS(m) ((m)->state == mu_sieve_state_disass) | ||
30 | #define INSTR_DEBUG(m) \ | 31 | #define INSTR_DEBUG(m) \ |
31 | (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE9)) | 32 | (INSTR_DISASS(m) || mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE9)) |
32 | #define INSTR_DISASS(m) \ | ||
33 | (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE8)) | ||
34 | 33 | ||
35 | void | 34 | void |
36 | _mu_i_sv_instr_source (mu_sieve_machine_t mach) | 35 | _mu_i_sv_instr_source (mu_sieve_machine_t mach) |
... | @@ -83,7 +82,7 @@ _mu_i_sv_instr_action (mu_sieve_machine_t mach) | ... | @@ -83,7 +82,7 @@ _mu_i_sv_instr_action (mu_sieve_machine_t mach) |
83 | { | 82 | { |
84 | mach->identifier = SIEVE_ARG (mach, 3, string); | 83 | mach->identifier = SIEVE_ARG (mach, 3, string); |
85 | mach->action_count++; | 84 | mach->action_count++; |
86 | instr_run (mach, "action"); | 85 | instr_run (mach, "ACTION"); |
87 | mach->identifier = NULL; | 86 | mach->identifier = NULL; |
88 | } | 87 | } |
89 | 88 | ||
... | @@ -91,7 +90,7 @@ void | ... | @@ -91,7 +90,7 @@ void |
91 | _mu_i_sv_instr_test (mu_sieve_machine_t mach) | 90 | _mu_i_sv_instr_test (mu_sieve_machine_t mach) |
92 | { | 91 | { |
93 | mach->identifier = SIEVE_ARG (mach, 3, string); | 92 | mach->identifier = SIEVE_ARG (mach, 3, string); |
94 | mach->reg = instr_run (mach, "test"); | 93 | mach->reg = instr_run (mach, "TEST"); |
95 | mach->identifier = NULL; | 94 | mach->identifier = NULL; |
96 | } | 95 | } |
97 | 96 | ||
... | @@ -99,11 +98,9 @@ void | ... | @@ -99,11 +98,9 @@ void |
99 | _mu_i_sv_instr_push (mu_sieve_machine_t mach) | 98 | _mu_i_sv_instr_push (mu_sieve_machine_t mach) |
100 | { | 99 | { |
101 | if (INSTR_DEBUG (mach)) | 100 | if (INSTR_DEBUG (mach)) |
102 | { | 101 | mu_i_sv_debug (mach, mach->pc - 1, "PUSH"); |
103 | mu_i_sv_debug (mach, mach->pc - 1, "PUSH"); | 102 | if (INSTR_DISASS (mach)) |
104 | if (INSTR_DISASS (mach)) | 103 | return; |
105 | return; | ||
106 | } | ||
107 | 104 | ||
108 | if (!mach->stack && mu_list_create (&mach->stack)) | 105 | if (!mach->stack && mu_list_create (&mach->stack)) |
109 | { | 106 | { |
... | @@ -117,11 +114,9 @@ void | ... | @@ -117,11 +114,9 @@ void |
117 | _mu_i_sv_instr_pop (mu_sieve_machine_t mach) | 114 | _mu_i_sv_instr_pop (mu_sieve_machine_t mach) |
118 | { | 115 | { |
119 | if (INSTR_DEBUG (mach)) | 116 | if (INSTR_DEBUG (mach)) |
120 | { | 117 | mu_i_sv_debug (mach, mach->pc - 1, "POP"); |
121 | mu_i_sv_debug (mach, mach->pc - 1, "POP"); | 118 | if (INSTR_DISASS (mach)) |
122 | if (INSTR_DISASS (mach)) | 119 | return; |
123 | return; | ||
124 | } | ||
125 | 120 | ||
126 | if (!mach->stack || mu_list_is_empty (mach->stack)) | 121 | if (!mach->stack || mu_list_is_empty (mach->stack)) |
127 | { | 122 | { |
... | @@ -135,11 +130,9 @@ void | ... | @@ -135,11 +130,9 @@ void |
135 | _mu_i_sv_instr_not (mu_sieve_machine_t mach) | 130 | _mu_i_sv_instr_not (mu_sieve_machine_t mach) |
136 | { | 131 | { |
137 | if (INSTR_DEBUG (mach)) | 132 | if (INSTR_DEBUG (mach)) |
138 | { | 133 | mu_i_sv_debug (mach, mach->pc - 1, "NOT"); |
139 | mu_i_sv_debug (mach, mach->pc - 1, "NOT"); | 134 | if (INSTR_DISASS (mach)) |
140 | if (INSTR_DISASS (mach)) | 135 | return; |
141 | return; | ||
142 | } | ||
143 | mach->reg = !mach->reg; | 136 | mach->reg = !mach->reg; |
144 | } | 137 | } |
145 | 138 | ||
... | @@ -150,12 +143,10 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach) | ... | @@ -150,12 +143,10 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach) |
150 | 143 | ||
151 | SIEVE_ADJUST (mach, 1); | 144 | SIEVE_ADJUST (mach, 1); |
152 | if (INSTR_DEBUG (mach)) | 145 | if (INSTR_DEBUG (mach)) |
153 | { | 146 | mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu", |
154 | mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu", | 147 | (unsigned long)(mach->pc + num)); |
155 | (unsigned long)(mach->pc + num)); | 148 | if (INSTR_DISASS (mach)) |
156 | if (INSTR_DISASS (mach)) | 149 | return; |
157 | return; | ||
158 | } | ||
159 | 150 | ||
160 | mach->pc += num; | 151 | mach->pc += num; |
161 | } | 152 | } |
... | @@ -167,12 +158,10 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach) | ... | @@ -167,12 +158,10 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach) |
167 | SIEVE_ADJUST (mach, 1); | 158 | SIEVE_ADJUST (mach, 1); |
168 | 159 | ||
169 | if (INSTR_DEBUG (mach)) | 160 | if (INSTR_DEBUG (mach)) |
170 | { | 161 | mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu", |
171 | mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu", | 162 | (unsigned long)(mach->pc + num)); |
172 | (unsigned long)(mach->pc + num)); | 163 | if (INSTR_DISASS (mach)) |
173 | if (INSTR_DISASS (mach)) | 164 | return; |
174 | return; | ||
175 | } | ||
176 | 165 | ||
177 | if (!mach->reg) | 166 | if (!mach->reg) |
178 | mach->pc += num; | 167 | mach->pc += num; |
... | @@ -185,12 +174,10 @@ _mu_i_sv_instr_brnz (mu_sieve_machine_t mach) | ... | @@ -185,12 +174,10 @@ _mu_i_sv_instr_brnz (mu_sieve_machine_t mach) |
185 | SIEVE_ADJUST (mach, 1); | 174 | SIEVE_ADJUST (mach, 1); |
186 | 175 | ||
187 | if (INSTR_DEBUG (mach)) | 176 | if (INSTR_DEBUG (mach)) |
188 | { | 177 | mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu", |
189 | mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu", | 178 | (unsigned long)(mach->pc + num)); |
190 | (unsigned long)(mach->pc + num)); | 179 | if (INSTR_DISASS (mach)) |
191 | if (INSTR_DISASS (mach)) | 180 | return; |
192 | return; | ||
193 | } | ||
194 | 181 | ||
195 | if (mach->reg) | 182 | if (mach->reg) |
196 | mach->pc += num; | 183 | mach->pc += num; |
... | @@ -262,35 +249,40 @@ mu_sieve_set_dry_run (mu_sieve_machine_t mach, int val) | ... | @@ -262,35 +249,40 @@ mu_sieve_set_dry_run (mu_sieve_machine_t mach, int val) |
262 | int | 249 | int |
263 | sieve_run (mu_sieve_machine_t mach) | 250 | sieve_run (mu_sieve_machine_t mach) |
264 | { | 251 | { |
265 | if (setjmp (mach->errbuf)) | 252 | int rc; |
266 | return 1; | ||
267 | 253 | ||
268 | mach->action_count = 0; | 254 | mu_sieve_stream_save (mach); |
269 | 255 | ||
270 | for (mach->pc = 1; mach->prog[mach->pc].handler; ) | 256 | rc = setjmp (mach->errbuf); |
271 | (*mach->prog[mach->pc++].instr) (mach); | 257 | if (rc == 0) |
258 | { | ||
259 | mach->action_count = 0; | ||
260 | |||
261 | for (mach->pc = 1; mach->prog[mach->pc].handler; ) | ||
262 | (*mach->prog[mach->pc++].instr) (mach); | ||
272 | 263 | ||
273 | if (mach->action_count == 0) | 264 | if (mach->action_count == 0) |
274 | mu_sieve_log_action (mach, "IMPLICIT KEEP", NULL); | 265 | mu_sieve_log_action (mach, "IMPLICIT KEEP", NULL); |
275 | 266 | ||
276 | if (INSTR_DEBUG (mach)) | 267 | if (INSTR_DEBUG (mach)) |
277 | mu_i_sv_debug (mach, mach->pc, "STOP"); | 268 | mu_i_sv_debug (mach, mach->pc, "STOP"); |
269 | } | ||
278 | 270 | ||
279 | return 0; | 271 | mu_sieve_stream_restore (mach); |
272 | |||
273 | return rc; | ||
280 | } | 274 | } |
281 | 275 | ||
282 | int | 276 | int |
283 | mu_sieve_disass (mu_sieve_machine_t mach) | 277 | mu_sieve_disass (mu_sieve_machine_t mach) |
284 | { | 278 | { |
285 | mu_debug_level_t lev; | ||
286 | int rc; | 279 | int rc; |
287 | 280 | ||
288 | mu_debug_get_category_level (mu_sieve_debug_handle, &lev); | 281 | if (mach->state != mu_sieve_state_compiled) |
289 | mu_debug_set_category_level (mu_sieve_debug_handle, | 282 | return EINVAL; /* FIXME: Error code */ |
290 | MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE8) | 283 | mach->state = mu_sieve_state_disass; |
291 | | MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE9)); | ||
292 | rc = sieve_run (mach); | 284 | rc = sieve_run (mach); |
293 | mu_debug_set_category_level (mu_sieve_debug_handle, lev); | 285 | mach->state = mu_sieve_state_compiled; |
294 | return rc; | 286 | return rc; |
295 | } | 287 | } |
296 | 288 | ... | ... |
... | @@ -45,12 +45,17 @@ struct mu_locus_range | ... | @@ -45,12 +45,17 @@ struct mu_locus_range |
45 | 45 | ||
46 | #define YYLTYPE struct mu_locus_range | 46 | #define YYLTYPE struct mu_locus_range |
47 | 47 | ||
48 | #define MU_SV_SAVED_ERR_STATE 0x01 | ||
49 | #define MU_SV_SAVED_DBG_STATE 0x02 | ||
50 | #define MU_SV_SAVED_STATE 0x80 | ||
51 | |||
48 | enum mu_sieve_state | 52 | enum mu_sieve_state |
49 | { | 53 | { |
50 | mu_sieve_state_init, | 54 | mu_sieve_state_init, |
51 | mu_sieve_state_error, | 55 | mu_sieve_state_error, |
52 | mu_sieve_state_compiled, | 56 | mu_sieve_state_compiled, |
53 | mu_sieve_state_running | 57 | mu_sieve_state_running, |
58 | mu_sieve_state_disass | ||
54 | }; | 59 | }; |
55 | 60 | ||
56 | struct mu_sieve_machine | 61 | struct mu_sieve_machine |
... | @@ -85,9 +90,17 @@ struct mu_sieve_machine | ... | @@ -85,9 +90,17 @@ struct mu_sieve_machine |
85 | size_t msgno; /* Current message number */ | 90 | size_t msgno; /* Current message number */ |
86 | mu_message_t msg; /* Current message */ | 91 | mu_message_t msg; /* Current message */ |
87 | int action_count; /* Number of actions executed over this message */ | 92 | int action_count; /* Number of actions executed over this message */ |
88 | 93 | ||
94 | /* Stream state info */ | ||
95 | int state_flags; | ||
96 | int err_mode; | ||
97 | struct mu_locus err_locus; | ||
98 | int dbg_mode; | ||
99 | struct mu_locus dbg_locus; | ||
100 | |||
89 | /* User supplied data */ | 101 | /* User supplied data */ |
90 | mu_stream_t errstream; | 102 | mu_stream_t errstream; |
103 | mu_stream_t dbgstream; | ||
91 | 104 | ||
92 | mu_sieve_action_log_t logger; | 105 | mu_sieve_action_log_t logger; |
93 | 106 | ... | ... |
... | @@ -994,8 +994,7 @@ mu_i_sv_error (mu_sieve_machine_t mach) | ... | @@ -994,8 +994,7 @@ mu_i_sv_error (mu_sieve_machine_t mach) |
994 | } | 994 | } |
995 | 995 | ||
996 | int | 996 | int |
997 | mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach, | 997 | mu_sieve_machine_init (mu_sieve_machine_t *pmach) |
998 | void *data, mu_stream_t errstream) | ||
999 | { | 998 | { |
1000 | int rc; | 999 | int rc; |
1001 | mu_sieve_machine_t mach; | 1000 | mu_sieve_machine_t mach; |
... | @@ -1022,33 +1021,46 @@ mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach, | ... | @@ -1022,33 +1021,46 @@ mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach, |
1022 | 1021 | ||
1023 | mach->source_list = NULL; | 1022 | mach->source_list = NULL; |
1024 | 1023 | ||
1025 | mach->data = data; | 1024 | mach->data = NULL; |
1026 | mach->errstream = errstream; | 1025 | |
1027 | mu_stream_ref (errstream); | 1026 | mu_sieve_set_diag_stream (mach, mu_strerr); |
1027 | mu_sieve_set_dbg_stream (mach, mu_strerr); | ||
1028 | 1028 | ||
1029 | *pmach = mach; | 1029 | *pmach = mach; |
1030 | return 0; | 1030 | return 0; |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | int | 1033 | int |
1034 | mu_sieve_machine_init (mu_sieve_machine_t *pmach) | ||
1035 | { | ||
1036 | return mu_sieve_machine_init_ex (pmach, NULL, mu_strerr); | ||
1037 | } | ||
1038 | |||
1039 | int | ||
1040 | mu_sieve_machine_inherit (mu_sieve_machine_t const parent, | 1034 | mu_sieve_machine_inherit (mu_sieve_machine_t const parent, |
1041 | mu_sieve_machine_t *pmach) | 1035 | mu_sieve_machine_t *pmach) |
1042 | { | 1036 | { |
1043 | mu_sieve_machine_t child; | 1037 | mu_sieve_machine_t child; |
1044 | int rc; | 1038 | int rc; |
1045 | 1039 | ||
1046 | rc = mu_sieve_machine_init_ex (&child, parent->data, parent->errstream); | 1040 | if (!parent || parent->state == mu_sieve_state_error) |
1041 | return EINVAL; | ||
1042 | |||
1043 | rc = mu_sieve_machine_init (&child); | ||
1047 | if (rc) | 1044 | if (rc) |
1048 | return rc; | 1045 | return rc; |
1049 | 1046 | ||
1047 | child->dry_run = parent->dry_run; | ||
1048 | |||
1049 | child->state_flags = parent->state_flags; | ||
1050 | child->err_mode = parent->err_mode; | ||
1051 | child->err_locus = parent->err_locus; | ||
1052 | child->dbg_mode = parent->dbg_mode; | ||
1053 | child->dbg_locus = parent->dbg_locus; | ||
1054 | |||
1055 | child->errstream = parent->errstream; | ||
1056 | mu_stream_ref (child->errstream); | ||
1057 | child->dbgstream = parent->dbgstream; | ||
1058 | mu_stream_ref (child->dbgstream); | ||
1059 | |||
1060 | child->data = parent->data; | ||
1050 | child->logger = parent->logger; | 1061 | child->logger = parent->logger; |
1051 | child->dry_run = parent->dry_run; | 1062 | child->daemon_email = parent->daemon_email; |
1063 | |||
1052 | *pmach = child; | 1064 | *pmach = child; |
1053 | return 0; | 1065 | return 0; |
1054 | } | 1066 | } |
... | @@ -1058,7 +1070,9 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) | ... | @@ -1058,7 +1070,9 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) |
1058 | { | 1070 | { |
1059 | int rc; | 1071 | int rc; |
1060 | mu_sieve_machine_t mach; | 1072 | mu_sieve_machine_t mach; |
1061 | 1073 | ||
1074 | if (!in || in->state == mu_sieve_state_error) | ||
1075 | return EINVAL; | ||
1062 | mach = malloc (sizeof (*mach)); | 1076 | mach = malloc (sizeof (*mach)); |
1063 | if (!mach) | 1077 | if (!mach) |
1064 | return ENOMEM; | 1078 | return ENOMEM; |
... | @@ -1077,15 +1091,33 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) | ... | @@ -1077,15 +1091,33 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, mu_sieve_machine_t *out) |
1077 | mach->progsize = in->progsize; | 1091 | mach->progsize = in->progsize; |
1078 | mach->prog = in->prog; | 1092 | mach->prog = in->prog; |
1079 | 1093 | ||
1080 | mach->state = in->state; | 1094 | switch (in->state) |
1095 | { | ||
1096 | case mu_sieve_state_running: | ||
1097 | case mu_sieve_state_disass: | ||
1098 | mach->state = mu_sieve_state_compiled; | ||
1099 | break; | ||
1100 | |||
1101 | default: | ||
1102 | mach->state = in->state; | ||
1103 | } | ||
1104 | |||
1081 | mach->pc = 0; | 1105 | mach->pc = 0; |
1082 | mach->reg = 0; | 1106 | mach->reg = 0; |
1083 | mach->stack = NULL; | 1107 | mach->stack = NULL; |
1084 | 1108 | ||
1085 | mach->dry_run = in->dry_run; | 1109 | mach->dry_run = in->dry_run; |
1086 | 1110 | ||
1111 | mach->state_flags = in->state_flags; | ||
1112 | mach->err_mode = in->err_mode; | ||
1113 | mach->err_locus = in->err_locus; | ||
1114 | mach->dbg_mode = in->dbg_mode; | ||
1115 | mach->dbg_locus = in->dbg_locus; | ||
1116 | |||
1087 | mach->errstream = in->errstream; | 1117 | mach->errstream = in->errstream; |
1088 | mu_stream_ref (mach->errstream); | 1118 | mu_stream_ref (mach->errstream); |
1119 | mach->dbgstream = in->dbgstream; | ||
1120 | mu_stream_ref (mach->dbgstream); | ||
1089 | 1121 | ||
1090 | mach->data = in->data; | 1122 | mach->data = in->data; |
1091 | mach->logger = in->logger; | 1123 | mach->logger = in->logger; |
... | @@ -1111,6 +1143,21 @@ mu_sieve_set_diag_stream (mu_sieve_machine_t mach, mu_stream_t str) | ... | @@ -1111,6 +1143,21 @@ mu_sieve_set_diag_stream (mu_sieve_machine_t mach, mu_stream_t str) |
1111 | } | 1143 | } |
1112 | 1144 | ||
1113 | void | 1145 | void |
1146 | mu_sieve_set_dbg_stream (mu_sieve_machine_t mach, mu_stream_t str) | ||
1147 | { | ||
1148 | mu_stream_unref (mach->dbgstream); | ||
1149 | mach->dbgstream = str; | ||
1150 | mu_stream_ref (mach->dbgstream); | ||
1151 | } | ||
1152 | |||
1153 | void | ||
1154 | mu_sieve_get_dbg_stream (mu_sieve_machine_t mach, mu_stream_t *pstr) | ||
1155 | { | ||
1156 | *pstr = mach->dbgstream; | ||
1157 | mu_stream_ref (*pstr); | ||
1158 | } | ||
1159 | |||
1160 | void | ||
1114 | mu_sieve_set_logger (mu_sieve_machine_t mach, mu_sieve_action_log_t logger) | 1161 | mu_sieve_set_logger (mu_sieve_machine_t mach, mu_sieve_action_log_t logger) |
1115 | { | 1162 | { |
1116 | mach->logger = logger; | 1163 | mach->logger = logger; |
... | @@ -1215,10 +1262,9 @@ void | ... | @@ -1215,10 +1262,9 @@ void |
1215 | mu_sieve_machine_destroy (mu_sieve_machine_t *pmach) | 1262 | mu_sieve_machine_destroy (mu_sieve_machine_t *pmach) |
1216 | { | 1263 | { |
1217 | mu_sieve_machine_t mach = *pmach; | 1264 | mu_sieve_machine_t mach = *pmach; |
1218 | /* FIXME: Restore stream state (locus & mode) */ | 1265 | |
1219 | mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, | ||
1220 | MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); | ||
1221 | mu_stream_destroy (&mach->errstream); | 1266 | mu_stream_destroy (&mach->errstream); |
1267 | mu_stream_destroy (&mach->dbgstream); | ||
1222 | mu_mailer_destroy (&mach->mailer); | 1268 | mu_mailer_destroy (&mach->mailer); |
1223 | mu_list_foreach (mach->destr_list, _run_destructor, NULL); | 1269 | mu_list_foreach (mach->destr_list, _run_destructor, NULL); |
1224 | mu_list_destroy (&mach->destr_list); | 1270 | mu_list_destroy (&mach->destr_list); |
... | @@ -1232,42 +1278,31 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach) | ... | @@ -1232,42 +1278,31 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach) |
1232 | *pmach = NULL; | 1278 | *pmach = NULL; |
1233 | } | 1279 | } |
1234 | 1280 | ||
1235 | static void | ||
1236 | sieve_machine_begin (mu_sieve_machine_t mach, const char *file) | ||
1237 | { | ||
1238 | mu_i_sv_register_standard_actions (mach); | ||
1239 | mu_i_sv_register_standard_tests (mach); | ||
1240 | mu_i_sv_register_standard_comparators (mach); | ||
1241 | mu_sieve_machine = mach; | ||
1242 | } | ||
1243 | |||
1244 | static void | ||
1245 | sieve_machine_finish (void) | ||
1246 | { | ||
1247 | //nothing | ||
1248 | } | ||
1249 | |||
1250 | int | 1281 | int |
1251 | with_machine (mu_sieve_machine_t mach, char const *name, | 1282 | with_machine (mu_sieve_machine_t mach, char const *name, |
1252 | int (*thunk) (void *), void *data) | 1283 | int (*thunk) (void *), void *data) |
1253 | { | 1284 | { |
1254 | int rc = 0; | 1285 | int rc = 0; |
1255 | mu_stream_t save_errstr = mu_strerr; | 1286 | mu_stream_t save_errstr; |
1256 | 1287 | ||
1288 | save_errstr = mu_strerr; | ||
1257 | mu_stream_ref (save_errstr); | 1289 | mu_stream_ref (save_errstr); |
1258 | mu_strerr = mach->errstream; | 1290 | mu_strerr = mach->errstream; |
1259 | mu_stream_ref (mu_strerr); | 1291 | mu_stream_ref (mu_strerr); |
1260 | 1292 | ||
1261 | sieve_machine_begin (mach, name); | 1293 | mu_i_sv_register_standard_actions (mach); |
1294 | mu_i_sv_register_standard_tests (mach); | ||
1295 | mu_i_sv_register_standard_comparators (mach); | ||
1296 | mu_sieve_machine = mach; | ||
1262 | 1297 | ||
1298 | mu_sieve_stream_save (mach); | ||
1263 | rc = thunk (data); | 1299 | rc = thunk (data); |
1264 | 1300 | mu_sieve_stream_restore (mach); | |
1265 | sieve_machine_finish (); | ||
1266 | 1301 | ||
1267 | mu_stream_unref (save_errstr); | 1302 | mu_stream_unref (save_errstr); |
1268 | mu_strerr = save_errstr; | 1303 | mu_strerr = save_errstr; |
1269 | mu_stream_unref (mu_strerr); | 1304 | mu_stream_unref (mu_strerr); |
1270 | 1305 | ||
1271 | return rc; | 1306 | return rc; |
1272 | } | 1307 | } |
1273 | 1308 | ... | ... |
... | @@ -267,17 +267,24 @@ mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...) | ... | @@ -267,17 +267,24 @@ mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...) |
267 | { | 267 | { |
268 | va_list ap; | 268 | va_list ap; |
269 | 269 | ||
270 | if (mach->state_flags & MU_SV_SAVED_DBG_STATE) | ||
271 | { | ||
272 | unsigned severity = MU_LOG_DEBUG; | ||
273 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
274 | MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity); | ||
275 | if (mach->locus.mu_file) | ||
276 | { | ||
277 | int mode = mach->dbg_mode | MU_LOGMODE_LOCUS; | ||
278 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
279 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus); | ||
280 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
281 | MU_IOCTL_LOGSTREAM_SET_MODE, &mode); | ||
282 | } | ||
283 | } | ||
270 | va_start (ap, fmt); | 284 | va_start (ap, fmt); |
271 | mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG); | 285 | mu_stream_printf (mach->dbgstream, "%4zu: ", pc); |
272 | if (mach->locus.mu_file) | 286 | mu_stream_vprintf (mach->dbgstream, fmt, ap); |
273 | mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>", | 287 | mu_stream_write (mach->dbgstream, "\n", 1, NULL); |
274 | MU_LOGMODE_LOCUS, | ||
275 | (unsigned) strlen (mach->locus.mu_file), | ||
276 | mach->locus.mu_file, | ||
277 | mach->locus.mu_line); | ||
278 | mu_stream_printf (mach->errstream, "%4zu: ", pc); | ||
279 | mu_stream_vprintf (mach->errstream, fmt, ap); | ||
280 | mu_stream_write (mach->errstream, "\n", 1, NULL); | ||
281 | va_end (ap); | 288 | va_end (ap); |
282 | } | 289 | } |
283 | 290 | ||
... | @@ -287,18 +294,25 @@ mu_i_sv_debug_command (mu_sieve_machine_t mach, | ... | @@ -287,18 +294,25 @@ mu_i_sv_debug_command (mu_sieve_machine_t mach, |
287 | char const *what, | 294 | char const *what, |
288 | mu_list_t taglist, mu_list_t arglist) | 295 | mu_list_t taglist, mu_list_t arglist) |
289 | { | 296 | { |
290 | mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG); | 297 | if (mach->state_flags & MU_SV_SAVED_DBG_STATE) |
291 | if (mach->locus.mu_file) | 298 | { |
292 | mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>", | 299 | unsigned severity = MU_LOG_DEBUG; |
293 | MU_LOGMODE_LOCUS, | 300 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, |
294 | (unsigned) strlen (mach->locus.mu_file), | 301 | MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity); |
295 | mach->locus.mu_file, | 302 | if (mach->locus.mu_file) |
296 | mach->locus.mu_line); | 303 | { |
297 | mu_stream_printf (mach->errstream, "%4zu: %s: %s", | 304 | int mode = mach->dbg_mode | MU_LOGMODE_LOCUS; |
305 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
306 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus); | ||
307 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
308 | MU_IOCTL_LOGSTREAM_SET_MODE, &mode); | ||
309 | } | ||
310 | } | ||
311 | mu_stream_printf (mach->dbgstream, "%4zu: %s: %s", | ||
298 | pc, what, mach->identifier); | 312 | pc, what, mach->identifier); |
299 | mu_i_sv_tagf (mach->errstream, taglist); | 313 | mu_i_sv_tagf (mach->dbgstream, taglist); |
300 | mu_i_sv_argf (mach->errstream, arglist); | 314 | mu_i_sv_argf (mach->dbgstream, arglist); |
301 | mu_stream_write (mach->errstream, "\n", 1, NULL); | 315 | mu_stream_write (mach->dbgstream, "\n", 1, NULL); |
302 | } | 316 | } |
303 | 317 | ||
304 | void | 318 | void |
... | @@ -434,9 +448,9 @@ _comp_action (void *item, void *data) | ... | @@ -434,9 +448,9 @@ _comp_action (void *item, void *data) |
434 | 448 | ||
435 | int | 449 | int |
436 | mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b, | 450 | mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b, |
437 | mu_sieve_comparator_t comp, mu_sieve_relcmp_t test, | 451 | mu_sieve_comparator_t comp, mu_sieve_relcmp_t test, |
438 | mu_sieve_retrieve_t retr, | 452 | mu_sieve_retrieve_t retr, |
439 | void *data, size_t *count) | 453 | void *data, size_t *count) |
440 | { | 454 | { |
441 | struct comp_data d; | 455 | struct comp_data d; |
442 | int rc; | 456 | int rc; |
... | @@ -452,3 +466,51 @@ mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b, | ... | @@ -452,3 +466,51 @@ mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b, |
452 | *count = d.count; | 466 | *count = d.count; |
453 | return rc; | 467 | return rc; |
454 | } | 468 | } |
469 | |||
470 | |||
471 | void | ||
472 | mu_sieve_stream_save (mu_sieve_machine_t mach) | ||
473 | { | ||
474 | if (mach->state_flags & MU_SV_SAVED_STATE) | ||
475 | return; | ||
476 | |||
477 | if (mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, | ||
478 | MU_IOCTL_LOGSTREAM_GET_MODE, &mach->err_mode) == 0 | ||
479 | && mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, | ||
480 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->err_locus) == 0) | ||
481 | mach->state_flags |= MU_SV_SAVED_ERR_STATE; | ||
482 | |||
483 | if (mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
484 | MU_IOCTL_LOGSTREAM_GET_MODE, &mach->dbg_mode) == 0 | ||
485 | && mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
486 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->dbg_locus) == 0) | ||
487 | mach->state_flags |= MU_SV_SAVED_DBG_STATE; | ||
488 | |||
489 | mach->state_flags |= MU_SV_SAVED_STATE; | ||
490 | } | ||
491 | |||
492 | void | ||
493 | mu_sieve_stream_restore (mu_sieve_machine_t mach) | ||
494 | { | ||
495 | if (!(mach->state_flags & MU_SV_SAVED_STATE)) | ||
496 | return; | ||
497 | |||
498 | if (mach->state_flags & MU_SV_SAVED_ERR_STATE) | ||
499 | { | ||
500 | mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, | ||
501 | MU_IOCTL_LOGSTREAM_SET_MODE, &mach->err_mode); | ||
502 | mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM, | ||
503 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->err_locus); | ||
504 | } | ||
505 | |||
506 | if (mach->dbgstream != mach->errstream | ||
507 | && (mach->state_flags & MU_SV_SAVED_DBG_STATE)) | ||
508 | { | ||
509 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
510 | MU_IOCTL_LOGSTREAM_SET_MODE, &mach->dbg_mode); | ||
511 | mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM, | ||
512 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->dbg_locus); | ||
513 | } | ||
514 | |||
515 | mach->state_flags = 0; | ||
516 | } | ... | ... |
... | @@ -5,3 +5,5 @@ | ... | @@ -5,3 +5,5 @@ |
5 | 5 | ||
6 | PATH=@abs_builddir@:@abs_top_builddir@/mail:$top_srcdir:$srcdir:$PATH | 6 | PATH=@abs_builddir@:@abs_top_builddir@/mail:$top_srcdir:$srcdir:$PATH |
7 | testsuitedir=@abs_top_srcdir@/testsuite | 7 | testsuitedir=@abs_top_srcdir@/testsuite |
8 | MALLOC_CHECK_=2 | ||
9 | export MALLOC_CHECK_ | ... | ... |
... | @@ -107,7 +107,9 @@ api_sieve_machine_init (PyObject *self, PyObject *args) | ... | @@ -107,7 +107,9 @@ api_sieve_machine_init (PyObject *self, PyObject *args) |
107 | if (status) | 107 | if (status) |
108 | return _ro (PyInt_FromLong (status)); | 108 | return _ro (PyInt_FromLong (status)); |
109 | 109 | ||
110 | status = mu_sieve_machine_init_ex (&py_mach->mach, NULL, estr); | 110 | status = mu_sieve_machine_init (&py_mach->mach); |
111 | if (status == 0) | ||
112 | mu_sieve_set_diag_stream (py_mach->mach, estr); | ||
111 | mu_stream_unref (estr); | 113 | mu_stream_unref (estr); |
112 | return _ro (PyInt_FromLong (status)); | 114 | return _ro (PyInt_FromLong (status)); |
113 | } | 115 | } | ... | ... |
... | @@ -247,12 +247,20 @@ static struct mu_cli_setup cli = { | ... | @@ -247,12 +247,20 @@ static struct mu_cli_setup cli = { |
247 | N_("GNU sieve -- a mail filtering tool."), | 247 | N_("GNU sieve -- a mail filtering tool."), |
248 | "SCRIPT", | 248 | "SCRIPT", |
249 | NULL, | 249 | NULL, |
250 | N_("Debug flags:\n\ | 250 | N_("Sieve-specific debug levels:\n\ |
251 | \n\ | ||
252 | trace1 - print parse tree before optimization\n\ | ||
253 | trace2 - print parse tree after optimization\n\ | ||
254 | trace3 - print parser traces\n\ | ||
255 | trace4 - print tests and actions being executed\n\ | ||
256 | trace9 - print each Sieve instruction being executed\n\ | ||
257 | \n\ | ||
258 | Compatibility debug flags:\n\ | ||
251 | g - main parser traces\n\ | 259 | g - main parser traces\n\ |
252 | T - mailutils traces (same as --debug-level=sieve.trace0-trace1)\n\ | 260 | T - mailutils traces (same as --debug-level=sieve.trace0-trace1)\n\ |
253 | P - network protocols (same as --debug-level=sieve.=prot)\n\ | 261 | P - network protocols (same as --debug-level=sieve.=prot)\n\ |
254 | t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\ | 262 | t - sieve trace (same as --debug-level=sieve.=trace4)\n\ |
255 | i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n") | 263 | i - sieve instructions trace (same as --debug-level=sieve.=trace9)\n") |
256 | }; | 264 | }; |
257 | 265 | ||
258 | static void | 266 | static void |
... | @@ -440,7 +448,10 @@ main (int argc, char *argv[]) | ... | @@ -440,7 +448,10 @@ main (int argc, char *argv[]) |
440 | if (compile_only) | 448 | if (compile_only) |
441 | { | 449 | { |
442 | if (compile_only == 2) | 450 | if (compile_only == 2) |
443 | mu_sieve_disass (mach); | 451 | { |
452 | mu_sieve_set_dbg_stream (mach, mu_strout); | ||
453 | mu_sieve_disass (mach); | ||
454 | } | ||
444 | return EX_OK; | 455 | return EX_OK; |
445 | } | 456 | } |
446 | 457 | ... | ... |
-
Please register or sign in to post a comment