commit 4cc5ad5a1ae5cbe8405b5391d5a9aefb19c38563
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Sun Apr 2 14:57:17 2017 +0200

    introduce driver call debugging
    
    do that by wrapping the actual stores into proxies.
    
    the proxy driver's code is auto-generated from function templates, some
    parameters, and the declarations of the driver functions themselves.
    attempts to do it with CPP macros turned out to be a nightmare.

 src/.gitignore       |   1 +
 src/Makefile.am      |  10 +-
 src/common.h         |   4 +-
 src/driver.h         |  11 +-
 src/drv_imap.c       |   1 +
 src/drv_maildir.c    |   1 +
 src/drv_proxy.c      | 335 +++++++++++++++++++++++++++++++++++++++++++
 src/drv_proxy_gen.pl | 169 ++++++++++++++++++++++
 src/main.c           |  29 ++--
 src/mbsync.1         |   8 +-
 src/sync.c           |  17 +--
 11 files changed, 553 insertions(+), 33 deletions(-)

diff --git a/src/.gitignore b/src/.gitignore
index 22be2da..d58dda7 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,4 @@
+/drv_proxy.inc
 /mbsync
 /mdconvert
 /tst_timers
diff --git a/src/Makefile.am b/src/Makefile.am
index b548d60..1634a2c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,10 +3,14 @@ compat_dir = compat
 endif
 SUBDIRS = $(compat_dir)
 
-mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c 
drv_maildir.c
+mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c 
drv_maildir.c drv_proxy.c
 mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS)
 noinst_HEADERS = common.h config.h driver.h sync.h socket.h
 
+drv_proxy.$(OBJEXT): drv_proxy.inc
+drv_proxy.inc: $(srcdir)/driver.h $(srcdir)/drv_proxy.c 
$(srcdir)/drv_proxy_gen.pl
+       perl $(srcdir)/drv_proxy_gen.pl $(srcdir)/driver.h 
$(srcdir)/drv_proxy.c drv_proxy.inc
+
 mdconvert_SOURCES = mdconvert.c
 mdconvert_LDADD = $(DB_LIBS)
 if with_mdconvert
@@ -24,4 +28,6 @@ man_MANS = mbsync.1 $(mdconvert_man)
 exampledir = $(docdir)/examples
 example_DATA = mbsyncrc.sample
 
-EXTRA_DIST = run-tests.pl $(example_DATA) $(man_MANS)
+EXTRA_DIST = drv_proxy_gen.pl run-tests.pl $(example_DATA) $(man_MANS)
+
+CLEANFILES = drv_proxy.inc
diff --git a/src/common.h b/src/common.h
index 0885927..ac3d2d3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -70,7 +70,9 @@ typedef unsigned int uint;
 #define DEBUG_NET_ALL   0x08
 #define DEBUG_SYNC      0x10
 #define DEBUG_MAIN      0x20
-#define DEBUG_ALL       (0xFF & ~DEBUG_NET_ALL)
+#define DEBUG_DRV       0x40
+#define DEBUG_DRV_ALL   0x80
+#define DEBUG_ALL       (0xFF & ~(DEBUG_NET_ALL | DEBUG_DRV_ALL))
 #define QUIET           0x100
 #define VERYQUIET       0x200
 #define PROGRESS        0x400
diff --git a/src/driver.h b/src/driver.h
index caf29c4..09b579d 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -87,6 +87,7 @@ typedef struct message {
 
 typedef struct store {
        struct store *next;
+       driver_t *driver;
        store_conf_t *conf; /* foreign */
 } store_t;
 
@@ -124,9 +125,11 @@ typedef struct {
 #define LIST_PATH       2
 #define LIST_PATH_MAYBE 4
 
+#define xint int  // For auto-generation of appropriate printf() formats.
+
 struct driver {
        /* Return driver capabilities. */
-       int (*get_caps)( store_t *ctx );
+       xint (*get_caps)( store_t *ctx );
 
        /* Parse configuration. */
        int (*parse_store)( conffile_t *cfg, store_conf_t **storep );
@@ -192,7 +195,7 @@ struct driver {
        /* Invoked before load_box(), this informs the driver which operations 
(OP_*)
         * will be performed on the mailbox. The driver may extend the set by 
implicitly
         * needed or available operations. Returns this possibly extended set. 
*/
-       int (*prepare_load_box)( store_t *ctx, int opts );
+       xint (*prepare_load_box)( store_t *ctx, xint opts );
 
        /* Load the message attributes needed to perform the requested 
operations.
         * Consider only messages with UIDs between minuid and maxuid 
(inclusive)
@@ -260,8 +263,10 @@ void free_generic_messages( message_t * );
 
 void parse_generic_store( store_conf_t *store, conffile_t *cfg );
 
+store_t *proxy_alloc_store( store_t *real_ctx, const char *label );
+
 #define N_DRIVERS 2
 extern driver_t *drivers[N_DRIVERS];
-extern driver_t maildir_driver, imap_driver;
+extern driver_t maildir_driver, imap_driver, proxy_driver;
 
 #endif
diff --git a/src/drv_imap.c b/src/drv_imap.c
index baba08d..2302703 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1708,6 +1708,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
        ctx->pending_append = &ctx->pending;
 
   gotsrv:
+       ctx->gen.driver = &imap_driver;
        ctx->gen.conf = conf;
        ctx->label = label;
        ctx->ref_count = 1;
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 2017c44..9176412 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -226,6 +226,7 @@ maildir_alloc_store( store_conf_t *gconf, const char *label 
ATTR_UNUSED )
        maildir_store_t *ctx;
 
        ctx = nfcalloc( sizeof(*ctx) );
+       ctx->gen.driver = &maildir_driver;
        ctx->gen.conf = gconf;
        ctx->uvfd = -1;
        init_wakeup( &ctx->lcktmr, lcktmr_timeout, ctx );
diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index e69de29..9754240 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -0,0 +1,335 @@
+/*
+ * mbsync - mailbox synchronizer
+ * Copyright (C) 2017 Oswald Buddenhagen <o...@users.sf.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, mbsync may be linked with the OpenSSL library,
+ * despite that library's more restrictive license.
+ */
+
+#include "driver.h"
+
+#include <limits.h>
+#include <stdlib.h>
+
+typedef struct {
+       store_t gen;
+       const char *label; // foreign
+       int ref_count;
+       driver_t *real_driver;
+       store_t *real_store;
+
+       void (*bad_callback)( void *aux );
+       void *bad_callback_aux;
+} proxy_store_t;
+
+static void ATTR_PRINTFLIKE(1, 2)
+debug( const char *msg, ... )
+{
+       va_list va;
+
+       va_start( va, msg );
+       vdebug( DEBUG_DRV, msg, va );
+       va_end( va );
+}
+
+static void ATTR_PRINTFLIKE(1, 2)
+debugn( const char *msg, ... )
+{
+       va_list va;
+
+       va_start( va, msg );
+       vdebugn( DEBUG_DRV, msg, va );
+       va_end( va );
+}
+
+static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' };
+
+static char *
+proxy_make_flags( int flags, char *buf )
+{
+       uint i, d;
+
+       for (d = 0, i = 0; i < as(Flags); i++)
+               if (flags & (1 << i))
+                       buf[d++] = Flags[i];
+       buf[d] = 0;
+       return buf;
+}
+
+static void
+proxy_store_deref( proxy_store_t *ctx )
+{
+       if (!--ctx->ref_count)
+               free( ctx );
+}
+
+static int curr_tag;
+
+typedef struct {
+       int ref_count;
+       int tag;
+       proxy_store_t *ctx;
+} gen_cmd_t;
+
+static gen_cmd_t *
+proxy_cmd_new( proxy_store_t *ctx, int sz )
+{
+       gen_cmd_t *cmd = nfmalloc( sz );
+       cmd->ref_count = 2;
+       cmd->tag = ++curr_tag;
+       cmd->ctx = ctx;
+       ctx->ref_count++;
+       return cmd;
+}
+
+static void
+proxy_cmd_done( gen_cmd_t *cmd )
+{
+       if (!--cmd->ref_count) {
+               proxy_store_deref( cmd->ctx );
+               free( cmd );
+       }
+}
+
+#if 0
+//# TEMPLATE GETTER
+static @type@proxy_@name@( store_t *gctx )
+{
+       proxy_store_t *ctx = (proxy_store_t *)gctx;
+
+       @type@rv = ctx->real_driver->@name@( ctx->real_store );
+       debug( "%sCalled @name@, ret=@fmt@\n", ctx->label, rv );
+       return rv;
+}
+//# END
+
+//# TEMPLATE REGULAR
+static @type@proxy_@name@( store_t *gctx@decl_args@ )
+{
+       proxy_store_t *ctx = (proxy_store_t *)gctx;
+
+       @pre_print_args@
+       debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ 
);
+       @print_args@
+       @type@rv = ctx->real_driver->@name@( ctx->real_store@pass_args@ );
+       debug( "%sLeave @name@, ret=@fmt@\n", ctx->label, rv );
+       return rv;
+}
+//# END
+
+//# TEMPLATE REGULAR_VOID
+static void proxy_@name@( store_t *gctx@decl_args@ )
+{
+       proxy_store_t *ctx = (proxy_store_t *)gctx;
+
+       @pre_print_args@
+       debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ 
);
+       @print_args@
+       ctx->real_driver->@name@( ctx->real_store@pass_args@ );
+       debug( "%sLeave @name@\n", ctx->label );
+       @action@
+}
+//# END
+
+//# TEMPLATE CALLBACK
+typedef struct {
+       gen_cmd_t gen;
+       void (*callback)( @decl_cb_args@void *aux );
+       void *callback_aux;
+       @decl_state@
+} @name@_cmd_t;
+
+static void
+proxy_@name@_cb( @decl_cb_args@void *aux )
+{
+       @name@_cmd_t *cmd = (@name@_cmd_t *)aux;
+
+       @pre_print_cb_args@
+       debug( "%s[% 2d] Callback enter @name@@print_fmt_cb_args@\n", 
cmd->gen.ctx->label, cmd->gen.tag@print_pass_cb_args@ );
+       @print_cb_args@
+       cmd->callback( @pass_cb_args@cmd->callback_aux );
+       debug( "%s[% 2d] Callback leave @name@\n", cmd->gen.ctx->label, 
cmd->gen.tag );
+       proxy_cmd_done( &cmd->gen );
+}
+
+static void
+proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), 
void *aux )
+{
+       proxy_store_t *ctx = (proxy_store_t *)gctx;
+
+       @name@_cmd_t *cmd = (@name@_cmd_t *)proxy_cmd_new( ctx, 
sizeof(@name@_cmd_t) );
+       cmd->callback = cb;
+       cmd->callback_aux = aux;
+       @assign_state@
+       @pre_print_args@
+       debug( "%s[% 2d] Enter @name@@print_fmt_args@\n", ctx->label, 
cmd->gen.tag@print_pass_args@ );
+       @print_args@
+       ctx->real_driver->@name@( ctx->real_store@pass_args@, proxy_@name@_cb, 
cmd );
+       debug( "%s[% 2d] Leave @name@\n", ctx->label, cmd->gen.tag );
+       proxy_cmd_done( &cmd->gen );
+}
+//# END
+
+//# UNDEFINE list_store_print_fmt_cb_args
+//# UNDEFINE list_store_print_pass_cb_args
+//# DEFINE list_store_print_cb_args
+       if (sts == DRV_OK) {
+               for (string_list_t *box = boxes; box; box = box->next)
+                       debug( "  %s\n", box->string );
+       }
+//# END
+
+//# DEFINE load_box_pre_print_args
+       static char ubuf[12];
+//# END
+//# DEFINE load_box_print_fmt_args , [%d,%s] (new >= %d, seen <= %d)
+//# DEFINE load_box_print_pass_args , minuid, (maxuid == INT_MAX) ? "inf" : 
(nfsnprintf( ubuf, sizeof(ubuf), "%d", maxuid ), ubuf), newuid, seenuid
+//# DEFINE load_box_print_args
+       if (excs.size) {
+               debugn( "  excs:" );
+               for (int t = 0; t < excs.size; t++)
+                       debugn( " %d", excs.data[t] );
+               debug( "\n" );
+       }
+//# END
+//# DEFINE load_box_pre_print_cb_args
+       static char fbuf[as(Flags) + 1];
+//# END
+//# DEFINE load_box_print_fmt_cb_args , sts=%d, total=%d, recent=%d
+//# DEFINE load_box_print_pass_cb_args , sts, total_msgs, recent_msgs
+//# DEFINE load_box_print_cb_args
+       if (sts == DRV_OK) {
+               for (message_t *msg = msgs; msg; msg = msg->next)
+                       debug( "  uid=%5d, flags=%4s, size=%6d, tuid=%." 
stringify(TUIDL) "s\n",
+                              msg->uid, (msg->status & M_FLAGS) ? 
(proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? 
msg->tuid : "?" );
+       }
+//# END
+
+//# DEFINE find_new_msgs_print_fmt_cb_args , sts=%d
+//# DEFINE find_new_msgs_print_pass_cb_args , sts
+//# DEFINE find_new_msgs_print_cb_args
+       if (sts == DRV_OK) {
+               for (message_t *msg = msgs; msg; msg = msg->next)
+                       debug( "  uid=%5d, tuid=%." stringify(TUIDL) "s\n", 
msg->uid, msg->tuid );
+       }
+//# END
+
+//# DEFINE fetch_msg_decl_state
+       msg_data_t *data;
+//# END
+//# DEFINE fetch_msg_assign_state
+       cmd->data = data;
+//# END
+//# DEFINE fetch_msg_print_fmt_args , uid=%d, want_flags=%s, want_date=%s
+//# DEFINE fetch_msg_print_pass_args , msg->uid, !(msg->status & M_FLAGS) ? 
"yes" : "no", data->date ? "yes" : "no"
+//# DEFINE fetch_msg_pre_print_cb_args
+       static char fbuf[as(Flags) + 1];
+       proxy_make_flags( cmd->data->flags, fbuf );
+//# END
+//# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%ld, size=%d
+//# DEFINE fetch_msg_print_pass_cb_args , fbuf, cmd->data->date, cmd->data->len
+//# DEFINE fetch_msg_print_cb_args
+       if (sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) {
+               printf( "%s=========\n", cmd->gen.ctx->label );
+               fwrite( cmd->data->data, cmd->data->len, 1, stdout );
+               printf( "%s=========\n", cmd->gen.ctx->label );
+               fflush( stdout );
+       }
+//# END
+
+//# DEFINE store_msg_pre_print_args
+       static char fbuf[as(Flags) + 1];
+       proxy_make_flags( data->flags, fbuf );
+//# END
+//# DEFINE store_msg_print_fmt_args , flags=%s, date=%ld, size=%d, to_trash=%s
+//# DEFINE store_msg_print_pass_args , fbuf, data->date, data->len, to_trash ? 
"yes" : "no"
+//# DEFINE store_msg_print_args
+       if (DFlags & DEBUG_DRV_ALL) {
+               printf( "%s>>>>>>>>>\n", ctx->label );
+               fwrite( data->data, data->len, 1, stdout );
+               printf( "%s>>>>>>>>>\n", ctx->label );
+               fflush( stdout );
+       }
+//# END
+
+//# DEFINE set_msg_flags_pre_print_args
+       static char fbuf1[as(Flags) + 1], fbuf2[as(Flags) + 1];
+       proxy_make_flags( add, fbuf1 );
+       proxy_make_flags( del, fbuf2 );
+//# END
+//# DEFINE set_msg_flags_print_fmt_args , uid=%d, add=%s, del=%s
+//# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2
+
+//# DEFINE trash_msg_print_fmt_args , uid=%d
+//# DEFINE trash_msg_print_pass_args , msg->uid
+
+//# DEFINE free_store_action
+       proxy_store_deref( ctx );
+//# END
+
+//# DEFINE cancel_store_action
+       proxy_store_deref( ctx );
+//# END
+#endif
+
+//# SPECIAL commit_cmds
+static void
+proxy_commit_cmds( store_t *gctx )
+{
+       // Currently a dummy in all real drivers.
+       (void) gctx;
+}
+
+//# SPECIAL set_bad_callback
+static void
+proxy_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux )
+{
+       proxy_store_t *ctx = (proxy_store_t *)gctx;
+
+       ctx->bad_callback = cb;
+       ctx->bad_callback_aux = aux;
+}
+
+static void
+proxy_invoke_bad_callback( proxy_store_t *ctx )
+{
+       debug( "%sCallback enter bad store\n", ctx->label );
+       ctx->bad_callback( ctx->bad_callback_aux );
+       debug( "%sCallback leave bad store\n", ctx->label ); \
+}
+
+//# EXCLUDE alloc_store
+store_t *
+proxy_alloc_store( store_t *real_ctx, const char *label )
+{
+       proxy_store_t *ctx;
+
+       ctx = nfcalloc( sizeof(*ctx) );
+       ctx->gen.driver = &proxy_driver;
+       ctx->gen.conf = real_ctx->conf;
+       ctx->ref_count = 1;
+       ctx->label = label;
+       ctx->real_driver = real_ctx->driver;
+       ctx->real_store = real_ctx;
+       ctx->real_driver->set_bad_callback( ctx->real_store, (void (*)(void 
*))proxy_invoke_bad_callback, ctx );
+       return &ctx->gen;
+}
+
+//# EXCLUDE parse_store
+//# EXCLUDE cleanup
+//# EXCLUDE get_fail_state
+
+#include "drv_proxy.inc"
diff --git a/src/drv_proxy_gen.pl b/src/drv_proxy_gen.pl
new file mode 100755
index 0000000..f2ef3fd
--- /dev/null
+++ b/src/drv_proxy_gen.pl
@@ -0,0 +1,169 @@
+#!/usr/bin/perl
+#
+# mbsync - mailbox synchronizer
+# Copyright (C) 2017 Oswald Buddenhagen <o...@users.sf.net>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, mbsync may be linked with the OpenSSL library,
+# despite that library's more restrictive license.
+#
+
+use strict;
+use warnings;
+
+die("Usage: $0 driver.h drv_proxy.c drv_proxy.inc\n")
+       if ($#ARGV != 2);
+
+my ($in_header, $in_source, $out_source) = @ARGV;
+
+my %templates;
+my %defines;
+my %excluded;
+my %special;
+
+open(my $ins, $in_source) or die("Cannot open $in_source: $!\n");
+my $template;
+my $define;
+my $conts;
+while (<$ins>) {
+       if ($template) {
+               if (/^\/\/\# END$/) {
+                       $templates{$template} = $conts;
+                       $template = undef;
+               } else {
+                       $conts .= $_;
+               }
+       } elsif ($define) {
+               if (/^\/\/\# END$/) {
+                       $defines{$define} = $conts;
+                       $define = undef;
+               } else {
+                       $conts .= $_;
+               }
+       } else {
+               if (/^\/\/\# TEMPLATE (\w+)$/) {
+                       $template = $1;
+                       $conts = "";
+               } elsif (/^\/\/\# DEFINE (\w+)$/) {
+                       $define = $1;
+                       $conts = "";
+               } elsif (/^\/\/\# DEFINE (\w+) (.*)$/) {
+                       $defines{$1} = $2;
+               } elsif (/^\/\/\# UNDEFINE (\w+)$/) {
+                       $defines{$1} = "";
+               } elsif (/^\/\/\# EXCLUDE (\w+)$/) {
+                       $excluded{$1} = 1;
+               } elsif (/^\/\/\# SPECIAL (\w+)$/) {
+                       $special{$1} = 1;
+               }
+       }
+}
+close($ins);
+
+open(my $inh, $in_header) or die("Cannot open $in_header: $!\n");
+my $sts = 0;
+my $cont = "";
+while (<$inh>) {
+       if ($sts == 0) {
+               if (/^struct driver \{$/) {
+                       $sts = 1;
+               }
+       } elsif ($sts == 1) {
+               if (/^\};$/) {
+                       $sts = 0;
+               } else {
+                       $cont .= $_;
+               }
+       }
+}
+close($inh);
+
+$cont =~ s,\n, ,g;
+$cont =~ s,/\*.*?\*/, ,g;
+$cont =~ s,\h+, ,g;
+my @ptypes = map { s,^ ,,r } split(/;/, $cont);
+pop @ptypes;  # last one is empty
+
+my @cmd_table;
+
+sub make_args($)
+{
+       $_ = shift;
+       s/(?:^|(?<=, ))(?:const )?\w+ \*?//g;
+       return $_;
+}
+
+sub type_to_format($)
+{
+       $_ = shift;
+       s/xint /\%\#x/g;
+       s/int /\%d/g;
+       s/const char \*/\%s/g;
+       return $_;
+}
+
+sub make_format($)
+{
+       $_ = type_to_format(shift);
+       s/, (\%\#?.)(\w+)/, $2=$1/g;
+       return $_;
+}
+
+open(my $outh, ">".$out_source) or die("Cannot create $out_source: $!\n");
+
+for (@ptypes) {
+       /^([\w* ]+)\(\*(\w+)\)\( (.*) \)$/ or die("Cannot parse prototype 
'$_'\n");
+       my ($cmd_type, $cmd_name, $cmd_args) = ($1, $2, $3);
+       if (defined($excluded{$cmd_name})) {
+               push @cmd_table, "0";
+               next;
+       }
+       push @cmd_table, "proxy_$cmd_name";
+       next if (defined($special{$cmd_name}));
+       my %replace;
+       $replace{'name'} = $cmd_name;
+       $replace{'type'} = $cmd_type;
+       $cmd_args =~ s/^store_t \*ctx// or die("Arguments '$cmd_args' don't 
start with 'store_t *ctx'\n");
+       if ($cmd_type eq "void " && $cmd_args =~ s/, void \(\*cb\)\( (.*)void 
\*aux \), void \*aux$//) {
+               my $cmd_cb_args = $1;
+               $replace{'decl_cb_args'} = $cmd_cb_args;
+               $replace{'pass_cb_args'} = make_args($cmd_cb_args);
+               my $cmd_print_cb_args = $cmd_cb_args =~ s/(.*), $/, $1/r;
+               $replace{'print_pass_cb_args'} = make_args($cmd_print_cb_args);
+               $replace{'print_fmt_cb_args'} = make_format($cmd_print_cb_args);
+               $template = "CALLBACK";
+       } elsif ($cmd_name =~ /^get_/) {
+               $template = "GETTER";
+               $replace{'fmt'} = type_to_format($cmd_type);
+       } elsif ($cmd_type eq "void ") {
+               $template = "REGULAR_VOID";
+       } else {
+               $template = "REGULAR";
+               $replace{'fmt'} = type_to_format($cmd_type);
+       }
+       $replace{'decl_args'} = $cmd_args;
+       $replace{'print_pass_args'} = $replace{'pass_args'} = 
make_args($cmd_args);
+       $replace{'print_fmt_args'} = make_format($cmd_args);
+       for (keys %defines) {
+               $replace{$1} = $defines{$_} if (/^${cmd_name}_(.*)$/);
+       }
+       my $text = $templates{$template};
+       $text =~ s/^\h*\@(\w+)\@\n/$replace{$1} \/\/ ""/smeg;
+       $text =~ s/\@(\w+)\@/$replace{$1} \/\/ ""/eg;
+       print $outh $text."\n";
+}
+
+print $outh "struct driver proxy_driver = {\n".join("", map { "\t$_,\n" } 
@cmd_table)."};\n";
+close $outh;
diff --git a/src/main.c b/src/main.c
index 279a1b5..929db08 100644
--- a/src/main.c
+++ b/src/main.c
@@ -462,6 +462,10 @@ main( int argc, char **argv )
                                                op = VERBOSE | DEBUG_ALL;
                                        else if (!strcmp( opt, "-crash" ))
                                                op = DEBUG_CRASH;
+                                       else if (!strcmp( opt, "-driver" ))
+                                               op = VERBOSE | DEBUG_DRV;
+                                       else if (!strcmp( opt, "-driver-all" ))
+                                               op = VERBOSE | DEBUG_DRV | 
DEBUG_DRV_ALL;
                                        else if (!strcmp( opt, "-maildir" ))
                                                op = VERBOSE | DEBUG_MAILDIR;
                                        else if (!strcmp( opt, "-main" ))
@@ -648,6 +652,12 @@ main( int argc, char **argv )
                                case 'C':
                                        op |= DEBUG_CRASH;
                                        break;
+                               case 'd':
+                                       op |= DEBUG_DRV | VERBOSE;
+                                       break;
+                               case 'D':
+                                       op |= DEBUG_DRV | DEBUG_DRV_ALL | 
VERBOSE;
+                                       break;
                                case 'm':
                                        op |= DEBUG_MAILDIR | VERBOSE;
                                        break;
@@ -811,14 +821,20 @@ sync_chans( main_vars_t *mvars, int ent )
                if (mvars->skip)
                        goto next2;
                mvars->state[M] = mvars->state[S] = ST_FRESH;
-               if (mvars->chan->stores[M]->driver->get_caps( 0 ) & 
mvars->chan->stores[S]->driver->get_caps( 0 ) & DRV_VERBOSE)
+               if ((DFlags & DEBUG_DRV) || 
(mvars->chan->stores[M]->driver->get_caps( 0 ) & 
mvars->chan->stores[S]->driver->get_caps( 0 ) & DRV_VERBOSE))
                        labels[M] = "M: ", labels[S] = "S: ";
                else
                        labels[M] = labels[S] = "";
                for (t = 0; t < 2; t++) {
-                       mvars->drv[t] = mvars->chan->stores[t]->driver;
-                       mvars->ctx[t] = mvars->drv[t]->alloc_store( 
mvars->chan->stores[t], labels[t] );
-                       mvars->drv[t]->set_bad_callback( mvars->ctx[t], 
store_bad, AUX );
+                       driver_t *drv = mvars->chan->stores[t]->driver;
+                       store_t *ctx = drv->alloc_store( 
mvars->chan->stores[t], labels[t] );
+                       if (DFlags & DEBUG_DRV) {
+                               drv = &proxy_driver;
+                               ctx = proxy_alloc_store( ctx, labels[t] );
+                       }
+                       mvars->drv[t] = drv;
+                       mvars->ctx[t] = ctx;
+                       drv->set_bad_callback( ctx, store_bad, AUX );
                }
                for (t = 0; ; t++) {
                        info( "Opening %s store %s...\n", str_ms[t], 
mvars->chan->stores[t]->name );
@@ -1008,11 +1024,6 @@ store_listed( int sts, string_list_t *boxes, void *aux )
        case DRV_CANCELED:
                return;
        case DRV_OK:
-               if (DFlags & DEBUG_MAIN) {
-                       debug( "got mailbox list from %s:\n", str_ms[t] );
-                       for (box = boxes; box; box = box->next)
-                               debug( "  %s\n", box->string );
-               }
                for (box = boxes; box; box = box->next) {
                        if (mvars->ctx[t]->conf->flat_delim) {
                                string_list_t *nbox;
diff --git a/src/mbsync.1 b/src/mbsync.1
index 627181e..cbf759e 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -83,12 +83,16 @@ Display version information.
 \fB-V\fR, \fB--verbose\fR
 Enable \fIverbose\fR mode, which displays what is currently happening.
 .TP
-\fB-D\fR[\fBC\fR][\fBm\fR][\fBM\fR][\fBn\fR|\fBN\fR][\fBs\fR]\fR]\fR,\
- 
\fB--debug\fR[\fB-crash\fR|\fB-maildir\fR|\fB-main\fR|\fB-net\fR|\fB-net-all\fR|\fB-sync\fR]
+\fB-D\fR[\fBC\fR][\fBd\fR|\fBD\fR][\fBm\fR][\fBM\fR][\fBn\fR|\fBN\fR][\fBs\fR]\fR]\fR,\
+ 
\fB--debug\fR[\fB-crash\fR|\fB-driver\fR|\fB-driver-all\fR|\fB-maildir\fR|\fB-main\fR|\fB-net\fR|\fB-net-all\fR|\fB-sync\fR]
 Enable debugging categories:
 .in +4
 \fBC\fR, \fBcrash\fR - use built-in crash handler
 .br
+\fBd\fR, \fBdriver\fR - print driver calls (metadata only)
+.br
+\fBD\fR, \fBdriver-all\fR - print driver calls (including messages)
+.br
 \fBm\fR, \fBmaildir\fR - print maildir debug info
 .br
 \fBM\fR, \fBmain\fR - print main debug info
diff --git a/src/sync.c b/src/sync.c
index b829958..1663939 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1003,7 +1003,7 @@ sync_boxes( store_t *ctx[], const char *names[], int 
present[], channel_conf_t *
                        sync_bail3( svars );
                        return;
                }
-               svars->drv[t] = ctx[t]->conf->driver;
+               svars->drv[t] = ctx[t]->driver;
                svars->drv[t]->set_bad_callback( ctx[t], store_bad, AUX );
        }
        /* Both boxes must be fully set up at this point, so that error exit 
paths
@@ -1284,10 +1284,6 @@ box_opened2( sync_vars_t *svars, int t )
                                }
                        }
                        sort_int_array( mexcs.array );
-                       debugn( "  exception list is:" );
-                       for (t = 0; t < mexcs.array.size; t++)
-                               debugn( " %d", mexcs.array.data[t] );
-                       debug( "\n" );
                } else {
                        minwuid = 1;
                }
@@ -1336,10 +1332,6 @@ load_box( sync_vars_t *svars, int t, int minwuid, 
int_array_t mexcs )
                seenuid = svars->maxuid[t];
        }
        info( "Loading %s...\n", str_ms[t] );
-       if (maxwuid == INT_MAX)
-               debug( "loading %s [%d,inf] (new >= %d, seen <= %d)\n", 
str_ms[t], minwuid, svars->newuid[t], seenuid );
-       else
-               debug( "loading %s [%d,%d] (new >= %d, seen <= %d)\n", 
str_ms[t], minwuid, maxwuid, svars->newuid[t], seenuid );
        svars->drv[t]->load_box( svars->ctx[t], minwuid, maxwuid, 
svars->newuid[t], seenuid, mexcs, box_loaded, AUX );
 }
 
@@ -1372,7 +1364,6 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
        int uid, no[2], del[2], alive, todel, t1, t2;
        int sflags, nflags, aflags, dflags;
        uint hashsz, idx;
-       char fbuf[16]; /* enlarge when support for keywords is added */
 
        if (check_ret( sts, aux ))
                return;
@@ -1406,10 +1397,6 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
                if (tmsg->srec) /* found by TUID */
                        continue;
                uid = tmsg->uid;
-               if (DFlags & DEBUG_SYNC) {
-                       make_flags( tmsg->flags, fbuf );
-                       printf( tmsg->size ? "  message %5d, %-4s, %6d: " : "  
message %5d, %-4s: ", uid, fbuf, tmsg->size );
-               }
                idx = (uint)((uint)uid * 1103515245U) % hashsz;
                while (srecmap[idx].uid) {
                        if (srecmap[idx].uid == uid) {
@@ -1419,12 +1406,10 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
                        if (++idx == hashsz)
                                idx = 0;
                }
-               debug( "new\n" );
                continue;
          found:
                tmsg->srec = srec;
                srec->msg[t] = tmsg;
-               debug( "pairs %5d\n", srec->uid[1-t] );
        }
        free( srecmap );
 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to