commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-3.0-11-g05df35d


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-3.0-11-g05df35d
Date: Thu, 24 Nov 2016 15:18:46 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=05df35d07a46f70e7d09a4da39fdd2d7a7d58ed0

The branch, master has been updated
       via  05df35d07a46f70e7d09a4da39fdd2d7a7d58ed0 (commit)
       via  a4c1a0e88bdeb8372ae66e27da4009a49b0f8009 (commit)
       via  d282d8e74e30328586a7c8e9a72a47a8f1fbce79 (commit)
       via  f617dd5dfc51dad7766c62c0cb70e5fcf0baf1b1 (commit)
      from  ffa85e25b9c3598b9b37205585894ad7318063d5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 05df35d07a46f70e7d09a4da39fdd2d7a7d58ed0
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 15:25:07 2016 +0200

    sieve: simplify action logging API
    
    * include/mailutils/sieve.h (mu_sieve_action_log_t): Change proto.
    * lib/sieve.c (_sieve_action_log): Rewrite.
    * libmu_sieve/util.c (mu_sieve_log_action): Rewrite.
    * python/libmu_py/sieve.c (_sieve_action_printer): Rewrite.
    * sieve/sieve.c (_sieve_action_log): Rewrite.

commit a4c1a0e88bdeb8372ae66e27da4009a49b0f8009
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 14:20:54 2016 +0200

    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.

commit d282d8e74e30328586a7c8e9a72a47a8f1fbce79
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 10:08:57 2016 +0200

    Sieve: remove unused opcode
    
    * libmu_sieve/runtime.c (_mu_i_sv_instr_nop): Remove.
    * libmu_sieve/sieve-priv.h: Likewise.

commit f617dd5dfc51dad7766c62c0cb70e5fcf0baf1b1
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Nov 24 09:55:18 2016 +0200

    Revamp debugging/tracing support
    
    * bootstrap.conf (mu_sieve_debug, mu_sieve_trace): Remove.
    * include/mailutils/sieve.h (mu_sieve_debug): Remove.
    
    * examples/numaddr.c: Remove calls to mu_sieve_trace.
    * 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.
    * libmu_sieve/tests.c: Likewise.
    
    * libmu_sieve/runtime.c: Use new debugging/tracing functions.
    * libmu_sieve/sieve-priv.h (mu_i_sv_debug, mu_i_sv_trace)
    (mu_i_sv_debug_command)
    (mu_i_sv_argf, mu_i_sv_valf): New prototypes.
    * libmu_sieve/sieve.y (mu_i_sv_valf, mu_i_sv_argf): New functions.
    * libmu_sieve/util.c (mu_sieve_debug): Remove.
    (mu_i_sv_print_value_list): Remove.
    (mu_i_sv_print_tag_list): Remove.
    (mu_sieve_trace): Remove.
    (mu_i_sv_tagf): New function.
    (mu_i_sv_debug): New function.
    (mu_i_sv_trace): New function.
    (mu_i_sv_debug_command): New function.

-----------------------------------------------------------------------

Summary of changes:
 bootstrap.conf                     |    1 -
 examples/numaddr.c                 |    2 -
 include/mailutils/sieve.h          |   22 ++-
 lib/sieve.c                        |   11 +-
 libmu_sieve/extensions/list.c      |    2 -
 libmu_sieve/extensions/moderator.c |    3 -
 libmu_sieve/extensions/pipe.c      |    2 -
 libmu_sieve/extensions/spamd.c     |    3 -
 libmu_sieve/extensions/timestamp.c |    2 -
 libmu_sieve/extensions/vacation.c  |    2 -
 libmu_sieve/runtime.c              |  145 ++++++++-----------
 libmu_sieve/sieve-priv.h           |   30 +++-
 libmu_sieve/sieve.y                |  140 ++++++++++++-------
 libmu_sieve/tests.c                |    8 --
 libmu_sieve/util.c                 |  272 +++++++++++++++++++-----------------
 mail/tests/atlocal.in              |    2 +
 python/libmu_py/sieve.c            |   21 +--
 sieve/sieve.c                      |   32 +++--
 18 files changed, 370 insertions(+), 330 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index d969396..6360a2c 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -47,7 +47,6 @@ XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
  --flag=mu_debug_print:3:c-format\\\
  --flag=mu_debug_printf:3:c-format\\\
  --flag=mu_sieve_error:2:c-format\\\
- --flag=mu_sieve_debug:2:c-format\\\
  --flag=mu_sieve_log_action:3:c-format\\\
  --flag=mu_nntp_writeline:2:c-format\\\
  --flag=mu_pop3_writeline:2:c-format\\\
diff --git a/examples/numaddr.c b/examples/numaddr.c
index 578bddc..66602ad 100644
--- a/examples/numaddr.c
+++ b/examples/numaddr.c
@@ -84,8 +84,6 @@ numaddr_test (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   struct val_ctr vc;
   int rc;
   
-  mu_sieve_trace (mach, "NUMADDR");
-
   /* Retrieve required arguments: */
   /* First argument: list of header names */
   h = mu_sieve_value_get (args, 0);
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index 74fa7c5..364a71a 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -35,9 +35,7 @@ typedef struct mu_sieve_machine *mu_sieve_machine_t;
 
 typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t mach,
                                   mu_list_t args, mu_list_t tags);
-typedef void (*mu_sieve_action_log_t) (void *data,
-                                      mu_stream_t stream,
-                                      size_t msgno, mu_message_t msg,
+typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach,
                                       const char *action,
                                       const char *fmt, va_list ap);
 
@@ -116,12 +114,6 @@ typedef struct
 #define MU_SIEVE_MATCH_EQ        5
 #define MU_SIEVE_MATCH_LAST      6
 
-/* Debugging levels */
-#define MU_SIEVE_DEBUG_TRACE  0x0001
-#define MU_SIEVE_DEBUG_INSTR  0x0002
-#define MU_SIEVE_DEBUG_DISAS  0x0004
-#define MU_SIEVE_DRY_RUN      0x0008
-
 extern mu_debug_handle_t mu_sieve_debug_handle;
 extern mu_list_t mu_sieve_include_path;
 extern mu_list_t mu_sieve_library_path;
@@ -212,9 +204,6 @@ int mu_sieve_vlist_compare (mu_sieve_value_t * a, 
mu_sieve_value_t * b,
 
 /* Functions to create and destroy sieve machine */
 int mu_sieve_machine_init (mu_sieve_machine_t *mach);
-int mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach,
-                             void *data,
-                             mu_stream_t errstream);
 int mu_sieve_machine_dup (mu_sieve_machine_t const in,
                          mu_sieve_machine_t *out);
 int mu_sieve_machine_inherit (mu_sieve_machine_t const in,
@@ -227,6 +216,9 @@ int mu_sieve_machine_add_destructor (mu_sieve_machine_t 
mach,
 void mu_sieve_get_diag_stream (mu_sieve_machine_t mach, mu_stream_t *pstr);
 void mu_sieve_set_diag_stream (mu_sieve_machine_t mach, mu_stream_t str);
 
+void mu_sieve_set_dbg_stream (mu_sieve_machine_t mach, mu_stream_t str);
+void mu_sieve_get_dbg_stream (mu_sieve_machine_t mach, mu_stream_t *pstr);
+
 void *mu_sieve_get_data (mu_sieve_machine_t mach);
 void mu_sieve_set_data (mu_sieve_machine_t mach, void *);
 mu_message_t mu_sieve_get_message (mu_sieve_machine_t mach);
@@ -247,12 +239,14 @@ void mu_sieve_set_daemon_email (mu_sieve_machine_t mach, 
const char *email);
 
 int mu_sieve_get_message_sender (mu_message_t msg, char **ptext);
 
+/* Stream state saving & restoring */
+void mu_sieve_stream_save (mu_sieve_machine_t mach);
+void mu_sieve_stream_restore (mu_sieve_machine_t mach);
+  
 /* Logging and diagnostic functions */
 
 void mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...) 
                      MU_PRINTFLIKE(2,3);
-void mu_sieve_debug (mu_sieve_machine_t mach, const char *fmt, ...)
-                     MU_PRINTFLIKE(2,3);
 void mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
                          const char *fmt, ...)
                          MU_PRINTFLIKE(3,4);
diff --git a/lib/sieve.c b/lib/sieve.c
index a7450c1..249b560 100644
--- a/lib/sieve.c
+++ b/lib/sieve.c
@@ -28,15 +28,17 @@ struct sieve_log_data
 };
 
 static void
-_sieve_action_log (void *data,
-                  mu_stream_t stream, size_t msgno,
-                  mu_message_t msg,
+_sieve_action_log (mu_sieve_machine_t mach,
                   const char *action, const char *fmt, va_list ap)
 {
-  struct sieve_log_data *ldat = data;
+  struct sieve_log_data *ldat = mu_sieve_get_data (mach);
   int pfx = 0;
+  mu_stream_t stream;
+  mu_message_t msg = mu_sieve_get_message (mach);
 
+  mu_sieve_get_diag_stream (mach, &stream);
   mu_stream_printf (stream, "\033s<%d>", MU_LOG_NOTICE);
+
   if (ldat)
     {
       if (ldat->user)
@@ -70,6 +72,7 @@ _sieve_action_log (void *data,
       mu_stream_vprintf (stream, fmt, ap);
     }
   mu_stream_printf (stream, "\n");
+  mu_stream_unref (stream);
 }
 
 static int
diff --git a/libmu_sieve/extensions/list.c b/libmu_sieve/extensions/list.c
index 46b7a25..ccde22d 100644
--- a/libmu_sieve/extensions/list.c
+++ b/libmu_sieve/extensions/list.c
@@ -152,8 +152,6 @@ list_test (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   struct header_closure clos;
   int result;
 
-  mu_sieve_trace (mach, "LIST");
-  
   memset (&clos, 0, sizeof clos);
   if (mu_sieve_tag_lookup (tags, "delim", &arg))
     clos.delim = arg->v.string;
diff --git a/libmu_sieve/extensions/moderator.c 
b/libmu_sieve/extensions/moderator.c
index 00b1de4..b19d0ed 100644
--- a/libmu_sieve/extensions/moderator.c
+++ b/libmu_sieve/extensions/moderator.c
@@ -273,9 +273,6 @@ moderator_action (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   int discard = 0;
   int ismime;
   
-  mu_sieve_trace (mach, "moderator_test %lu",
-                 (unsigned long) mu_sieve_get_message_num (mach));
-
   msg = mu_sieve_get_message (mach);
   mu_message_is_multipart (msg, &ismime);
 
diff --git a/libmu_sieve/extensions/pipe.c b/libmu_sieve/extensions/pipe.c
index 783950b..045c5a8 100644
--- a/libmu_sieve/extensions/pipe.c
+++ b/libmu_sieve/extensions/pipe.c
@@ -105,8 +105,6 @@ sieve_pipe (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags, int test)
     }
   cmd = val->v.string;
 
-  mu_sieve_trace (mach, test ? "PIPE (test)" : "PIPE (action)");
-
   if (mu_sieve_is_dry_run (mach))
     return 0;
 
diff --git a/libmu_sieve/extensions/spamd.c b/libmu_sieve/extensions/spamd.c
index 1fd8837..290d8b8 100644
--- a/libmu_sieve/extensions/spamd.c
+++ b/libmu_sieve/extensions/spamd.c
@@ -368,9 +368,6 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   mu_header_t hdr;
   mu_debug_handle_t lev = 0;
   
-  mu_sieve_trace (mach, "spamd_test %lu",
-                 (unsigned long) mu_sieve_get_message_num (mach));
-  
   if (mu_sieve_is_dry_run (mach))
     return 0;
   
diff --git a/libmu_sieve/extensions/timestamp.c 
b/libmu_sieve/extensions/timestamp.c
index 67fceb0..56c12f2 100644
--- a/libmu_sieve/extensions/timestamp.c
+++ b/libmu_sieve/extensions/timestamp.c
@@ -57,8 +57,6 @@ timestamp_test (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   time_t tlimit, tval;
   int rc;
   
-  mu_sieve_trace (mach, "TIMESTAMP");
-
   /* Retrieve required arguments: */
   /* First argument: header name */
   h = mu_sieve_value_get (args, 0);
diff --git a/libmu_sieve/extensions/vacation.c 
b/libmu_sieve/extensions/vacation.c
index 863fe15..8b8fefc 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -136,8 +136,6 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, 
mu_mime_t *pmime,
 static int
 diag (mu_sieve_machine_t mach)
 {
-  mu_sieve_trace (mach, "VACATION");
-
   mu_sieve_log_action (mach, "VACATION", NULL);
   return mu_sieve_is_dry_run (mach);
 }
diff --git a/libmu_sieve/runtime.c b/libmu_sieve/runtime.c
index 2778739..4648b9a 100644
--- a/libmu_sieve/runtime.c
+++ b/libmu_sieve/runtime.c
@@ -27,17 +27,9 @@
 #define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t)
 #define SIEVE_ADJUST(m,n) (m)->pc+=(n)
 
+#define INSTR_DISASS(m) ((m)->state == mu_sieve_state_disass)
 #define INSTR_DEBUG(m) \
-  (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE9)) 
-#define INSTR_DISASS(m) \
-  (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE8)) 
-
-void
-_mu_i_sv_instr_nop (mu_sieve_machine_t mach)
-{
-  if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: NOP", (unsigned long) (mach->pc - 1));
-}
+  (INSTR_DISASS(m) || mu_debug_level_p (mu_sieve_debug_handle, 
MU_DEBUG_TRACE9)) 
 
 void
 _mu_i_sv_instr_source (mu_sieve_machine_t mach)
@@ -47,9 +39,7 @@ _mu_i_sv_instr_source (mu_sieve_machine_t mach)
                    MU_IOCTL_LOGSTREAM_SET_LOCUS,
                   &mach->locus);
   if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: SOURCE %s",
-                   (unsigned long) (mach->pc - 1),
-                   mach->locus.mu_file);
+    mu_i_sv_debug (mach, mach->pc - 1, "SOURCE %s", mach->locus.mu_file);
   SIEVE_ADJUST (mach, 1);
 }
                 
@@ -61,14 +51,13 @@ _mu_i_sv_instr_line (mu_sieve_machine_t mach)
                    MU_IOCTL_LOGSTREAM_SET_LOCUS,
                   &mach->locus);
   if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: LINE %u",
-                (unsigned long) (mach->pc - 1),
-                mach->locus.mu_line);
+    mu_i_sv_debug (mach, mach->pc - 1, "LINE %u",
+                  mach->locus.mu_line);
   SIEVE_ADJUST (mach, 1);
 }
                 
 static int
-instr_run (mu_sieve_machine_t mach)
+instr_run (mu_sieve_machine_t mach, char const *what)
 {
   mu_sieve_handler_t han = SIEVE_ARG (mach, 0, handler);
   mu_list_t arg_list = SIEVE_ARG (mach, 1, list);
@@ -78,15 +67,11 @@ instr_run (mu_sieve_machine_t mach)
   SIEVE_ADJUST(mach, 4);
 
   if (INSTR_DEBUG (mach))
-    {
-      mu_stream_printf (mach->errstream,
-                       "\033s<%d>Arguments: ", MU_LOG_DEBUG);
-      mu_i_sv_print_value_list (arg_list, mach->errstream);
-      mu_stream_printf (mach->errstream, "\n\033s<%d>Tags: ", MU_LOG_DEBUG);
-      mu_i_sv_print_tag_list (tag_list, mach->errstream);
-      mu_stream_printf (mach->errstream, "\n");
-    }
-
+    mu_i_sv_debug_command (mach, mach->pc - 1,
+                          what, tag_list, arg_list);
+  else
+    mu_i_sv_trace (mach, what, tag_list, arg_list);
+  
   if (!INSTR_DISASS(mach))
     rc = han (mach, arg_list, tag_list);
   return rc;
@@ -96,12 +81,8 @@ void
 _mu_i_sv_instr_action (mu_sieve_machine_t mach)
 {
   mach->identifier = SIEVE_ARG (mach, 3, string);
-  if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: ACTION: %s",
-                   (unsigned long) (mach->pc - 1),
-                   mach->identifier);
   mach->action_count++;
-  instr_run (mach);
+  instr_run (mach, "ACTION");
   mach->identifier = NULL;
 }
 
@@ -109,11 +90,7 @@ void
 _mu_i_sv_instr_test (mu_sieve_machine_t mach)
 {
   mach->identifier = SIEVE_ARG (mach, 3, string);
-  if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: TEST: %s",
-                   (unsigned long) (mach->pc - 1),
-                   mach->identifier);
-  mach->reg = instr_run (mach);
+  mach->reg = instr_run (mach, "TEST");
   mach->identifier = NULL;
 }
 
@@ -121,11 +98,9 @@ void
 _mu_i_sv_instr_push (mu_sieve_machine_t mach)
 {
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: PUSH", (unsigned long)(mach->pc - 1));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 1, "PUSH");
+  if (INSTR_DISASS (mach))
+    return;
   
   if (!mach->stack && mu_list_create (&mach->stack))
     {
@@ -139,11 +114,9 @@ void
 _mu_i_sv_instr_pop (mu_sieve_machine_t mach)
 {
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: POP", (unsigned long)(mach->pc - 1));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 1, "POP");
+  if (INSTR_DISASS (mach))
+    return;
 
   if (!mach->stack || mu_list_is_empty (mach->stack))
     {
@@ -157,11 +130,9 @@ void
 _mu_i_sv_instr_not (mu_sieve_machine_t mach)
 {
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: NOT", (unsigned long)(mach->pc - 1));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 1, "NOT");
+  if (INSTR_DISASS (mach))
+    return;
   mach->reg = !mach->reg;
 }
 
@@ -172,13 +143,10 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach)
 
   SIEVE_ADJUST (mach, 1);
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: BRANCH %lu",
-                     (unsigned long)(mach->pc-2),
-                     (unsigned long)(mach->pc + num));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu",
+                  (unsigned long)(mach->pc + num));
+  if (INSTR_DISASS (mach))
+    return;
 
   mach->pc += num;
 }
@@ -190,13 +158,10 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach)
   SIEVE_ADJUST (mach, 1);
 
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: BRZ %lu",
-                     (unsigned long)(mach->pc-2),
-                     (unsigned long)(mach->pc + num));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu",
+                  (unsigned long)(mach->pc + num));
+  if (INSTR_DISASS (mach))
+    return;
   
   if (!mach->reg)
     mach->pc += num;
@@ -209,13 +174,10 @@ _mu_i_sv_instr_brnz (mu_sieve_machine_t mach)
   SIEVE_ADJUST (mach, 1);
 
   if (INSTR_DEBUG (mach))
-    {
-      mu_sieve_debug (mach, "%4lu: BRNZ %lu",
-                     (unsigned long)(mach->pc-2),
-                     (unsigned long)(mach->pc + num));
-      if (INSTR_DISASS (mach))
-       return;
-    }
+    mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu",
+                  (unsigned long)(mach->pc + num));
+  if (INSTR_DISASS (mach))
+    return;
   
   if (mach->reg)
     mach->pc += num;
@@ -287,35 +249,40 @@ mu_sieve_set_dry_run (mu_sieve_machine_t mach, int val)
 int
 sieve_run (mu_sieve_machine_t mach)
 {
-  if (setjmp (mach->errbuf))
-    return 1;
+  int rc;
 
-  mach->action_count = 0;
+  mu_sieve_stream_save (mach);
+  
+  rc = setjmp (mach->errbuf);
+  if (rc == 0)
+    {
+      mach->action_count = 0;
   
-  for (mach->pc = 1; mach->prog[mach->pc].handler; )
-    (*mach->prog[mach->pc++].instr) (mach);
+      for (mach->pc = 1; mach->prog[mach->pc].handler; )
+       (*mach->prog[mach->pc++].instr) (mach);
 
-  if (mach->action_count == 0)
-    mu_sieve_log_action (mach, "IMPLICIT KEEP", NULL);
+      if (mach->action_count == 0)
+       mu_sieve_log_action (mach, "IMPLICIT KEEP", NULL);
   
-  if (INSTR_DEBUG (mach))
-    mu_sieve_debug (mach, "%4lu: STOP", (unsigned long) mach->pc);
+      if (INSTR_DEBUG (mach))
+       mu_i_sv_debug (mach, mach->pc, "STOP");
+    }
   
-  return 0;
+  mu_sieve_stream_restore (mach);
+  
+  return rc;
 }
 
 int
 mu_sieve_disass (mu_sieve_machine_t mach)
 {
-  mu_debug_level_t lev;
   int rc;
-  
-  mu_debug_get_category_level (mu_sieve_debug_handle, &lev);
-  mu_debug_set_category_level (mu_sieve_debug_handle,
-                              MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE8)
-                              | MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE9));
+
+  if (mach->state != mu_sieve_state_compiled)
+    return EINVAL; /* FIXME: Error code */
+  mach->state = mu_sieve_state_disass;
   rc = sieve_run (mach);
-  mu_debug_set_category_level (mu_sieve_debug_handle, lev);
+  mach->state = mu_sieve_state_compiled;
   return rc;
 }
   
diff --git a/libmu_sieve/sieve-priv.h b/libmu_sieve/sieve-priv.h
index 1ff62d9..12aafaa 100644
--- a/libmu_sieve/sieve-priv.h
+++ b/libmu_sieve/sieve-priv.h
@@ -45,12 +45,17 @@ struct mu_locus_range
   
 #define YYLTYPE struct mu_locus_range
 
+#define MU_SV_SAVED_ERR_STATE 0x01
+#define MU_SV_SAVED_DBG_STATE 0x02
+#define MU_SV_SAVED_STATE     0x80
+
 enum mu_sieve_state
   {
     mu_sieve_state_init,
     mu_sieve_state_error,
     mu_sieve_state_compiled,
-    mu_sieve_state_running
+    mu_sieve_state_running,
+    mu_sieve_state_disass
   };
 
 struct mu_sieve_machine
@@ -85,9 +90,17 @@ struct mu_sieve_machine
   size_t    msgno;           /* Current message number */
   mu_message_t msg;          /* Current message */
   int action_count;          /* Number of actions executed over this message */
-                           
+
+  /* Stream state info */
+  int state_flags;
+  int err_mode;
+  struct mu_locus err_locus;
+  int dbg_mode;
+  struct mu_locus dbg_locus;
+  
   /* User supplied data */
   mu_stream_t errstream;
+  mu_stream_t dbgstream;
   
   mu_sieve_action_log_t logger;
   
@@ -165,7 +178,6 @@ void _mu_i_sv_instr_not (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_branch (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_brz (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_brnz (mu_sieve_machine_t mach);
-void _mu_i_sv_instr_nop (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_source (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_line (mu_sieve_machine_t mach);
 
@@ -180,3 +192,15 @@ void mu_i_sv_print_tag_list (mu_list_t list, mu_stream_t 
str);
 
 void mu_i_sv_error (mu_sieve_machine_t mach);
 
+void mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...)
+  MU_PRINTFLIKE(3,4);
+void mu_i_sv_debug_command (mu_sieve_machine_t mach,
+                           size_t pc,
+                           char const *what,
+                           mu_list_t taglist, mu_list_t arglist);
+void mu_i_sv_trace (mu_sieve_machine_t mach, const char *what,
+                   mu_list_t taglist, mu_list_t arglist);
+
+void mu_i_sv_argf (mu_stream_t str, mu_list_t list);
+void mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val);
+
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve.y
index 86fb962..eaa1cfc 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve.y
@@ -502,12 +502,9 @@ string_dumper (void *item, void *data)
   return 0;
 }
 
-static int
-dump_val (void *item, void *data)
+void
+mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val)
 {
-  mu_sieve_value_t *val = item;
-  mu_stream_t str = data;
-
   mu_stream_printf (str, " ");
   switch (val->type)
     {
@@ -544,7 +541,7 @@ dump_val (void *item, void *data)
        
     case SVT_VALUE_LIST:
       mu_stream_printf (str, "[");
-      mu_list_foreach (val->v.list, dump_val, str);
+      mu_i_sv_argf (str, val->v.list);
       mu_stream_printf (str, "]");
       break;
       
@@ -555,9 +552,23 @@ dump_val (void *item, void *data)
     default:
       abort ();
     }
-  return 0;
 }
   
+static int
+dump_val (void *item, void *data)
+{
+  mu_sieve_value_t *val = item;
+  mu_stream_t str = data;
+  mu_i_sv_valf (str, val);
+  return 0;
+}
+
+void
+mu_i_sv_argf (mu_stream_t str, mu_list_t list)
+{
+  mu_list_foreach (list, dump_val, str);
+}
+
 static void
 dump_node_command (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
 {
@@ -983,8 +994,7 @@ mu_i_sv_error (mu_sieve_machine_t mach)
 }
 
 int
-mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach,
-                         void *data, mu_stream_t errstream)
+mu_sieve_machine_init (mu_sieve_machine_t *pmach)
 {
   int rc;
   mu_sieve_machine_t mach;
@@ -1011,33 +1021,46 @@ mu_sieve_machine_init_ex (mu_sieve_machine_t *pmach,
   
   mach->source_list = NULL;
 
-  mach->data = data;
-  mach->errstream = errstream;
-  mu_stream_ref (errstream);
+  mach->data = NULL;
+
+  mu_sieve_set_diag_stream (mach, mu_strerr);
+  mu_sieve_set_dbg_stream (mach, mu_strerr);
   
   *pmach = mach;
   return 0;
 }
 
 int
-mu_sieve_machine_init (mu_sieve_machine_t *pmach)
-{
-  return mu_sieve_machine_init_ex (pmach, NULL, mu_strerr);
-}
-
-int
 mu_sieve_machine_inherit (mu_sieve_machine_t const parent,
                          mu_sieve_machine_t *pmach)
 {
   mu_sieve_machine_t child;
   int rc;
   
-  rc = mu_sieve_machine_init_ex (&child, parent->data, parent->errstream);
+  if (!parent || parent->state == mu_sieve_state_error)
+    return EINVAL;
+  
+  rc = mu_sieve_machine_init (&child);
   if (rc)
     return rc;
 
+  child->dry_run     = parent->dry_run;
+
+  child->state_flags = parent->state_flags;
+  child->err_mode    = parent->err_mode;
+  child->err_locus   = parent->err_locus;
+  child->dbg_mode    = parent->dbg_mode;
+  child->dbg_locus   = parent->dbg_locus;  
+
+  child->errstream = parent->errstream;
+  mu_stream_ref (child->errstream);
+  child->dbgstream = parent->dbgstream;
+  mu_stream_ref (child->dbgstream);
+  
+  child->data = parent->data;
   child->logger = parent->logger;
-  child->dry_run = parent->dry_run;
+  child->daemon_email = parent->daemon_email;
+
   *pmach = child;
   return 0;
 }
@@ -1047,7 +1070,9 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, 
mu_sieve_machine_t *out)
 {
   int rc;
   mu_sieve_machine_t mach;
-  
+
+  if (!in || in->state == mu_sieve_state_error)
+    return EINVAL; 
   mach = malloc (sizeof (*mach));
   if (!mach)
     return ENOMEM;
@@ -1066,15 +1091,33 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, 
mu_sieve_machine_t *out)
   mach->progsize = in->progsize;
   mach->prog = in->prog;
 
-  mach->state = in->state;
+  switch (in->state)
+    {
+    case mu_sieve_state_running:
+    case mu_sieve_state_disass:
+      mach->state = mu_sieve_state_compiled;
+      break;
+
+    default:
+      mach->state = in->state;
+    }
+  
   mach->pc = 0;
   mach->reg = 0;
   mach->stack = NULL;
 
   mach->dry_run = in->dry_run;
-  
+
+  mach->state_flags = in->state_flags;
+  mach->err_mode    = in->err_mode;
+  mach->err_locus   = in->err_locus;
+  mach->dbg_mode    = in->dbg_mode;
+  mach->dbg_locus   = in->dbg_locus;  
+
   mach->errstream = in->errstream;
   mu_stream_ref (mach->errstream);
+  mach->dbgstream = in->dbgstream;
+  mu_stream_ref (mach->dbgstream);
   
   mach->data = in->data;
   mach->logger = in->logger;
@@ -1100,6 +1143,21 @@ mu_sieve_set_diag_stream (mu_sieve_machine_t mach, 
mu_stream_t str)
 }
 
 void
+mu_sieve_set_dbg_stream (mu_sieve_machine_t mach, mu_stream_t str)
+{
+  mu_stream_unref (mach->dbgstream);
+  mach->dbgstream = str;
+  mu_stream_ref (mach->dbgstream);
+}
+
+void
+mu_sieve_get_dbg_stream (mu_sieve_machine_t mach, mu_stream_t *pstr)
+{
+  *pstr = mach->dbgstream;
+  mu_stream_ref (*pstr);
+}
+
+void
 mu_sieve_set_logger (mu_sieve_machine_t mach, mu_sieve_action_log_t logger)
 {
   mach->logger = logger;
@@ -1204,10 +1262,9 @@ void
 mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
 {
   mu_sieve_machine_t mach = *pmach;
-  /* FIXME: Restore stream state (locus & mode) */
-  mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
-                   MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
+
   mu_stream_destroy (&mach->errstream);
+  mu_stream_destroy (&mach->dbgstream);
   mu_mailer_destroy (&mach->mailer);
   mu_list_foreach (mach->destr_list, _run_destructor, NULL);
   mu_list_destroy (&mach->destr_list);
@@ -1221,42 +1278,31 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
   *pmach = NULL;
 }
 
-static void
-sieve_machine_begin (mu_sieve_machine_t mach, const char *file)
-{
-  mu_i_sv_register_standard_actions (mach);
-  mu_i_sv_register_standard_tests (mach);
-  mu_i_sv_register_standard_comparators (mach);
-  mu_sieve_machine = mach;
-}
-
-static void
-sieve_machine_finish (void)
-{
-  //nothing
-}
-
 int
 with_machine (mu_sieve_machine_t mach, char const *name,
              int (*thunk) (void *), void *data)
 {
   int rc = 0;
-  mu_stream_t save_errstr = mu_strerr;
-  
+  mu_stream_t save_errstr;
+
+  save_errstr = mu_strerr;  
   mu_stream_ref (save_errstr);
   mu_strerr = mach->errstream;
   mu_stream_ref (mu_strerr);
 
-  sieve_machine_begin (mach, name);
+  mu_i_sv_register_standard_actions (mach);
+  mu_i_sv_register_standard_tests (mach);
+  mu_i_sv_register_standard_comparators (mach);
+  mu_sieve_machine = mach;
 
+  mu_sieve_stream_save (mach);
   rc = thunk (data);
-
-  sieve_machine_finish ();
+  mu_sieve_stream_restore (mach);
 
   mu_stream_unref (save_errstr);
   mu_strerr = save_errstr;
   mu_stream_unref (mu_strerr);
-
+  
   return rc;
 }
 
diff --git a/libmu_sieve/tests.c b/libmu_sieve/tests.c
index 5d3efee..88adbe6 100644
--- a/libmu_sieve/tests.c
+++ b/libmu_sieve/tests.c
@@ -119,8 +119,6 @@ sieve_test_address (mu_sieve_machine_t mach, mu_list_t 
args, mu_list_t tags)
   int rc;
   size_t count;
   
-  mu_sieve_trace (mach, "ADDRESS");
-
   h = mu_sieve_value_get (args, 0);
   if (!h)
     {
@@ -182,8 +180,6 @@ sieve_test_header (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   size_t count, mcount = 0;
   struct header_closure clos;
   
-  mu_sieve_trace (mach, "HEADER");
-
   h = mu_sieve_value_get (args, 0);
   if (!h)
     {
@@ -265,8 +261,6 @@ sieve_test_envelope (mu_sieve_machine_t mach, mu_list_t 
args, mu_list_t tags)
   int rc;
   size_t count;
   
-  mu_sieve_trace (mach, "ENVELOPE");
-
   h = mu_sieve_value_get (args, 0);
   if (!h)
     {
@@ -331,8 +325,6 @@ sieve_test_exists (mu_sieve_machine_t mach, mu_list_t args, 
mu_list_t tags)
   mu_header_t header = NULL;
   mu_sieve_value_t *val;   
 
-  mu_sieve_trace (mach, "EXISTS");
-
   mu_message_get_header (mu_sieve_get_message (mach), &header);
   val = mu_sieve_value_get (args, 0);
   if (!val)
diff --git a/libmu_sieve/util.c b/libmu_sieve/util.c
index d0538b8..8b437c7 100644
--- a/libmu_sieve/util.c
+++ b/libmu_sieve/util.c
@@ -210,67 +210,7 @@ mu_sieve_arg_error (mu_sieve_machine_t mach, int n)
 {
   mu_sieve_error (mach, _("cannot retrieve argument %d"), n);
 }
-
-void
-mu_sieve_debug (mu_sieve_machine_t mach, const char *fmt, ...)
-{
-  va_list ap;
-
-  va_start (ap, fmt);
-  mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG);
-  if (mach->locus.mu_file)
-    mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
-                     MU_LOGMODE_LOCUS,
-                     (unsigned) strlen (mach->locus.mu_file),
-                     mach->locus.mu_file,
-                     mach->locus.mu_line);
-  mu_stream_vprintf (mach->errstream, fmt, ap);
-  mu_stream_write (mach->errstream, "\n", 1, NULL);
-  va_end (ap);
-}
-
-void
-mu_sieve_trace (mu_sieve_machine_t mach, const char *fmt, ...)
-{
-  va_list ap;
-
-  if (!mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE4))
-    return;
-  
-  va_start (ap, fmt);
-  mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG);
-  if (mach->locus.mu_file)
-    mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
-                     MU_LOGMODE_LOCUS,
-                     (unsigned) strlen (mach->locus.mu_file),
-                     mach->locus.mu_file,
-                     mach->locus.mu_line);
-  mu_stream_vprintf (mach->errstream, fmt, ap);
-  mu_stream_write (mach->errstream, "\n", 1, NULL);
-  va_end (ap);
-}
-
-void
-mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
-                    const char *fmt, ...)
-{
-  va_list ap;
-  
-  if (!mach->logger)
-    return;
-  va_start (ap, fmt);
-  mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_INFO);
-  if (mach->locus.mu_file)
-    mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
-                     MU_LOGMODE_LOCUS,
-                     (unsigned) strlen (mach->locus.mu_file),
-                     mach->locus.mu_file,
-                     mach->locus.mu_line);
-  mach->logger (mach->data, mach->errstream, mach->msgno, mach->msg,
-               action, fmt, ap);
-  va_end (ap);
-}
-  
+
 const char *
 mu_sieve_type_str (mu_sieve_data_type type)
 {
@@ -303,95 +243,115 @@ mu_sieve_type_str (mu_sieve_data_type type)
 
   return "unknown";
 }
-
+
 static int
-string_printer (void *item, void *data)
+tag_printer (void *item, void *data)
 {
-  char *s = item;
+  mu_sieve_runtime_tag_t *val = item;
   mu_stream_t str = data;
-
-  mu_stream_printf (str, "\"%s\" ", s);
+  
+  mu_stream_printf (str, " :%s", val->tag);
+  if (val->arg)
+    mu_i_sv_valf (str, val->arg);
   return 0;
 }
 
-static void sieve_print_value (mu_sieve_value_t *, mu_stream_t str);
-
-static int
-value_printer (void *item, void *data)
+void
+mu_i_sv_tagf (mu_stream_t str, mu_list_t taglist)
 {
-  mu_sieve_value_t *val = item;
-  mu_stream_t str = data;
-  
-  sieve_print_value (val, str);
-  mu_stream_printf (str, " ");
-  return 0;
+  mu_list_foreach (taglist, tag_printer, str);
 }
 
-static void
-sieve_print_value (mu_sieve_value_t *val, mu_stream_t str)
+void
+mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...)
 {
-  mu_stream_printf (str, "%s(", mu_sieve_type_str (val->type));
-  switch (val->type)
-    {
-    case SVT_VOID:
-      break;
-      
-    case SVT_NUMBER:
-      mu_stream_printf (str, "%lu", (unsigned long) val->v.number);
-      break;
-      
-    case SVT_TAG:
-    case SVT_IDENT:
-    case SVT_STRING:
-      mu_stream_printf (str, "%s", val->v.string);
-      break;
-      
-    case SVT_STRING_LIST:
-      mu_list_foreach (val->v.list, string_printer, str);
-      break;
-
-    case SVT_VALUE_LIST:
-      mu_list_foreach (val->v.list, value_printer, str);
+  va_list ap;
 
-    case SVT_POINTER:
-      mu_stream_printf (str, "%p", val->v.ptr);
+  if (mach->state_flags & MU_SV_SAVED_DBG_STATE)
+    {
+      unsigned severity = MU_LOG_DEBUG;
+      mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+      if (mach->locus.mu_file)
+       {
+         int mode = mach->dbg_mode | MU_LOGMODE_LOCUS;
+         mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                          MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
+         mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                          MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+       }
     }
-  mu_stream_printf (str, ")");
-} 
+  va_start (ap, fmt);
+  mu_stream_printf (mach->dbgstream, "%4zu: ", pc);
+  mu_stream_vprintf (mach->dbgstream, fmt, ap);
+  mu_stream_write (mach->dbgstream, "\n", 1, NULL);
+  va_end (ap);
+}
 
 void
-mu_i_sv_print_value_list (mu_list_t list, mu_stream_t str)
+mu_i_sv_debug_command (mu_sieve_machine_t mach,
+                      size_t pc,
+                      char const *what,
+                      mu_list_t taglist, mu_list_t arglist)
 {
-  mu_sieve_value_t val;
-  
-  val.type = SVT_VALUE_LIST;
-  val.v.list = list;
-  sieve_print_value (&val, str);
+  if (mach->state_flags & MU_SV_SAVED_DBG_STATE)
+    {
+      unsigned severity = MU_LOG_DEBUG;
+      mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_SEVERITY, &severity);
+      if (mach->locus.mu_file)
+       {
+         int mode = mach->dbg_mode | MU_LOGMODE_LOCUS;
+         mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                          MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
+         mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                          MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+       }
+    }
+  mu_stream_printf (mach->dbgstream, "%4zu: %s: %s",
+                   pc, what, mach->identifier);  
+  mu_i_sv_tagf (mach->dbgstream, taglist);
+  mu_i_sv_argf (mach->dbgstream, arglist);
+  mu_stream_write (mach->dbgstream, "\n", 1, NULL);
 }
 
-static int
-tag_printer (void *item, void *data)
+void
+mu_i_sv_trace (mu_sieve_machine_t mach, const char *what,
+              mu_list_t taglist, mu_list_t arglist)
 {
-  mu_sieve_runtime_tag_t *val = item;
-  mu_stream_t str = data;
+  if (!mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE4))
+    return;
   
-  mu_stream_printf (str, "%s", val->tag);
-  if (val->arg)
-    {
-      mu_stream_printf (str, "(");
-      sieve_print_value (val->arg, str);
-      mu_stream_printf (str, ")");
-    }
-  mu_stream_printf (str, " ");
-  return 0;
+  mu_stream_printf (mach->errstream, "\033s<%d>", MU_LOG_DEBUG);
+  if (mach->locus.mu_file)
+    mu_stream_printf (mach->errstream, "\033O<%d>\033f<%u>%s\033l<%u>",
+                     MU_LOGMODE_LOCUS,
+                     (unsigned) strlen (mach->locus.mu_file),
+                     mach->locus.mu_file,
+                     mach->locus.mu_line);
+  mu_stream_printf (mach->errstream, "%zu: %s %s", mach->msgno, what,
+                   mach->identifier);
+  mu_i_sv_tagf (mach->errstream, taglist);
+  mu_i_sv_argf (mach->errstream, arglist);
+  mu_stream_printf (mach->errstream, "\n");
 }
 
 void
-mu_i_sv_print_tag_list (mu_list_t list, mu_stream_t str)
+mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
+                    const char *fmt, ...)
 {
-  mu_list_foreach (list, tag_printer, str);
+  va_list ap;
+  
+  if (!mach->logger)
+    return;
+  
+  mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+                  MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->locus);
+  va_start (ap, fmt);
+  mach->logger (mach, action, fmt, ap);
+  va_end (ap);
 }
-
+  
 static int
 tag_finder (void *item, void *data)
 {
@@ -437,7 +397,8 @@ mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t 
ac, void *data)
     }
 }
 
-struct comp_data {
+struct comp_data
+{
   mu_sieve_value_t *val;
   mu_sieve_comparator_t comp;
   mu_sieve_relcmp_t test;
@@ -446,7 +407,8 @@ struct comp_data {
   size_t count;
 };
 
-struct comp_data2 {
+struct comp_data2
+{
   char *sample;
   mu_sieve_comparator_t comp;
   mu_sieve_relcmp_t test;
@@ -481,9 +443,9 @@ _comp_action (void *item, void *data)
 
 int
 mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b,
-                    mu_sieve_comparator_t comp, mu_sieve_relcmp_t test,
-                    mu_sieve_retrieve_t retr,
-                    void *data, size_t *count)
+                       mu_sieve_comparator_t comp, mu_sieve_relcmp_t test,
+                       mu_sieve_retrieve_t retr,
+                       void *data, size_t *count)
 {
   struct comp_data d;
   int rc;
@@ -499,3 +461,51 @@ mu_sieve_vlist_compare (mu_sieve_value_t *a, 
mu_sieve_value_t *b,
     *count = d.count;
   return rc;
 }
+
+
+void
+mu_sieve_stream_save (mu_sieve_machine_t mach)
+{
+  if (mach->state_flags & MU_SV_SAVED_STATE)
+    return;
+  
+  if (mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_GET_MODE, &mach->err_mode) == 0
+      && mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+                         MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->err_locus) == 0)
+      mach->state_flags |= MU_SV_SAVED_ERR_STATE;
+
+  if (mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_GET_MODE, &mach->dbg_mode) == 0
+      && mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                         MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->dbg_locus) == 0)
+    mach->state_flags |= MU_SV_SAVED_DBG_STATE;
+  
+  mach->state_flags |= MU_SV_SAVED_STATE;
+}
+
+void
+mu_sieve_stream_restore (mu_sieve_machine_t mach)
+{
+  if (!(mach->state_flags & MU_SV_SAVED_STATE))
+    return;
+
+  if (mach->state_flags & MU_SV_SAVED_ERR_STATE)
+    {
+      mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_MODE, &mach->err_mode);
+      mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->err_locus);
+    }
+  
+  if (mach->dbgstream != mach->errstream
+      && (mach->state_flags & MU_SV_SAVED_DBG_STATE))
+    {
+      mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_MODE, &mach->dbg_mode);
+      mu_stream_ioctl (mach->dbgstream, MU_IOCTL_LOGSTREAM,
+                      MU_IOCTL_LOGSTREAM_SET_LOCUS, &mach->dbg_locus);
+    }
+  
+  mach->state_flags = 0;
+}
diff --git a/mail/tests/atlocal.in b/mail/tests/atlocal.in
index 2516e66..73cd349 100644
--- a/mail/tests/atlocal.in
+++ b/mail/tests/atlocal.in
@@ -5,3 +5,5 @@
 
 address@hidden@:@abs_top_builddir@/mail:$top_srcdir:$srcdir:$PATH
 address@hidden@/testsuite
+MALLOC_CHECK_=2
+export MALLOC_CHECK_
diff --git a/python/libmu_py/sieve.c b/python/libmu_py/sieve.c
index d025fe6..baa3fb0 100644
--- a/python/libmu_py/sieve.c
+++ b/python/libmu_py/sieve.c
@@ -107,7 +107,9 @@ api_sieve_machine_init (PyObject *self, PyObject *args)
   if (status)
     return _ro (PyInt_FromLong (status));
   
-  status = mu_sieve_machine_init_ex (&py_mach->mach, NULL, estr);
+  status = mu_sieve_machine_init (&py_mach->mach);
+  if (status == 0)
+    mu_sieve_set_diag_stream (py_mach->mach, estr);
   mu_stream_unref (estr);
   return _ro (PyInt_FromLong (status));
 }
@@ -234,8 +236,7 @@ api_sieve_message (PyObject *self, PyObject *args)
 }
 
 static void
-_sieve_action_printer (void *data, mu_stream_t stream,
-                      size_t msgno, mu_message_t msg,
+_sieve_action_printer (mu_sieve_machine_t mach,
                       const char *action, const char *fmt, va_list ap)
 {
   PyObject *py_args;
@@ -256,10 +257,12 @@ _sieve_action_printer (void *data, mu_stream_t stream,
          PyStream *py_stm = PyStream_NEW ();
          if (py_stm)
            {
-             py_stm->stm = stream;
-             mu_stream_ref (stream);
-         
-             py_msg->msg = msg;
+             size_t msgno;
+             
+             mu_sieve_get_diag_stream (mach, &py_stm->stm);
+             msgno = mu_sieve_get_message_num (mach);
+             
+             py_msg->msg = mu_sieve_get_message (mach);
              Py_INCREF (py_msg);
 
              PyDict_SetItemString (py_dict, "msgno",
@@ -270,7 +273,7 @@ _sieve_action_printer (void *data, mu_stream_t stream,
 
              if (mu_vasnprintf (&buf, &buflen, fmt, ap))
                {
-                 mu_stream_unref (stream);
+                 mu_stream_destroy (&py_stm->stm);
                  return;
                }
              PyDict_SetItemString (py_dict, "text",
@@ -280,7 +283,7 @@ _sieve_action_printer (void *data, mu_stream_t stream,
              py_args = PyTuple_New (1);
              if (py_args)
                {
-                 struct _mu_py_sieve_logger *s = data;
+                 struct _mu_py_sieve_logger *s = mu_sieve_get_data (mach);
                  PyObject *py_fnc = s->py_action_printer;
 
                  Py_INCREF (py_dict);
diff --git a/sieve/sieve.c b/sieve/sieve.c
index 0f7789a..e5e066c 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -247,27 +247,38 @@ static struct mu_cli_setup cli = {
   N_("GNU sieve -- a mail filtering tool."),
   "SCRIPT",
   NULL,
-  N_("Debug flags:\n\
+  N_("Sieve-specific debug levels:\n\
+\n\
+  trace1  -  print parse tree before optimization\n\
+  trace2  -  print parse tree after optimization\n\
+  trace3  -  print parser traces\n\
+  trace4  -  print tests and actions being executed\n\
+  trace9  -  print each Sieve instruction being executed\n\
+\n\
+Compatibility debug flags:\n\
   g - main parser traces\n\
   T - mailutils traces (same as --debug-level=sieve.trace0-trace1)\n\
   P - network protocols (same as --debug-level=sieve.=prot)\n\
-  t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
-  i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n")
+  t - sieve trace (same as --debug-level=sieve.=trace4)\n\
+  i - sieve instructions trace (same as --debug-level=sieve.=trace9)\n")
 };
 
 static void
-_sieve_action_log (void *unused,
-                  mu_stream_t stream, size_t msgno,
-                  mu_message_t msg,
+_sieve_action_log (mu_sieve_machine_t mach,
                   const char *action, const char *fmt, va_list ap)
 {
   size_t uid = 0;
+  mu_message_t msg;
+  mu_stream_t stream;
+
+  mu_sieve_get_diag_stream (mach, &stream);
+  msg = mu_sieve_get_message (mach);
   
   mu_message_get_uid (msg, &uid);
   mu_stream_printf (stream, "\033s<%d>\033%c<%d>", MU_LOG_NOTICE,
                    sieve_print_locus ? 'O' : 'X', MU_LOGMODE_LOCUS);
   mu_stream_printf (stream, _("%s on msg uid %lu"),
-                 action, (unsigned long) uid);
+                   action, (unsigned long) uid);
   
   if (fmt && strlen (fmt))
     {
@@ -275,6 +286,8 @@ _sieve_action_log (void *unused,
       mu_stream_vprintf (stream, fmt, ap);
     }
   mu_stream_printf (stream, "\n");
+
+  mu_stream_unref (stream);
 }
 
 static int
@@ -440,7 +453,10 @@ main (int argc, char *argv[])
   if (compile_only)
     {
       if (compile_only == 2)
-       mu_sieve_disass (mach);
+       {
+         mu_sieve_set_dbg_stream (mach, mu_strout);
+         mu_sieve_disass (mach);
+       }
       return EX_OK;
     }
 


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]