Commit a4c1a0e8 a4c1a0e88bdeb8372ae66e27da4009a49b0f8009 by Sergey Poznyakoff

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.
1 parent d282d8e7
...@@ -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
......