commit ee832951e2bc2030abe49b1436760a597bd55382
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Mon Jul 24 12:04:13 2023 +0200

    revamp automatic enumeration of power-of-two enumerators
    
    i found a neat trick to do it with the C pre-processor after all.
    this makes the enum definitions themselves arguably somewhat less
    legible, but on the upside the build system becomes simpler, and IDEs
    can build/update their code models without having to (re-)build the
    project first.
    
    somewhat as a side effect, this gives bit enums proper names, so we
    don't need to refer to them by cryptic prefixes anymore.
    
    amends 6a78e2c5f.

 src/.gitignore      |   1 -
 src/Makefile.am     |  26 +--------
 src/bit_enum_gen.pl |  70 -----------------------
 src/common.h        | 131 ++++++++++++++++++++++++++++++--------------
 src/config.c        |   2 +-
 src/driver.h        |  83 ++++++++++++++--------------
 src/drv_imap.c      |   2 +-
 src/drv_proxy.c     |   2 +-
 src/sync.c          |  37 ++++++-------
 src/sync.h          |  57 ++++++++++---------
 src/sync_p.h        |  43 ++++++++-------
 src/sync_state.c    |   2 +-
 12 files changed, 207 insertions(+), 249 deletions(-)

diff --git a/src/.gitignore b/src/.gitignore
index 3139876..dea9ee7 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,4 +1,3 @@
-/*_enum.h
 /drv_proxy.inc
 /mbsync
 /mdconvert
diff --git a/src/Makefile.am b/src/Makefile.am
index 69cf29d..42d14f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,28 +20,6 @@ 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
 
-ENUM_GEN = $(srcdir)/bit_enum_gen.pl
-
-$(mbsync_OBJECTS): common_enum.h
-common_enum.h: common.h $(ENUM_GEN)
-       perl $(ENUM_GEN) < $< > $@
-
-$(mbsync_OBJECTS): driver_enum.h
-driver_enum.h: driver.h $(ENUM_GEN)
-       perl $(ENUM_GEN) < $< > $@
-
-$(mbsync_OBJECTS): sync_enum.h
-sync_enum.h: sync.h $(ENUM_GEN)
-       perl $(ENUM_GEN) < $< > $@
-
-sync.$(OBJEXT): sync_c_enum.h
-sync_c_enum.h: sync.c $(ENUM_GEN)
-       perl $(ENUM_GEN) < $< > $@
-
-sync.$(OBJEXT) sync_state.$(OBJEXT): sync_p_enum.h
-sync_p_enum.h: sync_p.h $(ENUM_GEN)
-       perl $(ENUM_GEN) < $< > $@
-
 mdconvert_SOURCES = mdconvert.c
 mdconvert_LDADD = $(DB_LIBS)
 if with_mdconvert
@@ -69,6 +47,6 @@ EXTRA_PROGRAMS = tst_timers
 exampledir = $(docdir)/examples
 example_DATA = mbsyncrc.sample
 
-EXTRA_DIST = bit_enum_gen.pl drv_proxy_gen.pl run-tests.pl $(example_DATA) 
$(man_MANS)
+EXTRA_DIST = drv_proxy_gen.pl run-tests.pl $(example_DATA) $(man_MANS)
 
-CLEANFILES = *_enum.h drv_proxy.inc
+CLEANFILES = drv_proxy.inc
diff --git a/src/bit_enum_gen.pl b/src/bit_enum_gen.pl
deleted file mode 100755
index 2b1ee21..0000000
--- a/src/bit_enum_gen.pl
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/perl
-#
-# SPDX-FileCopyrightText: 2022 Oswald Buddenhagen <o...@users.sf.net>
-# SPDX-License-Identifier: GPL-2.0-or-later
-#
-# mbsync - mailbox synchronizer
-#
-
-use strict;
-use warnings;
-
-my $in_enum = 0;
-my $conts;
-while (<>) {
-       s,\s*(?://.*)?$,,;
-       if ($in_enum) {
-               if (/^\)$/) {
-                       $conts =~ s/\s//g;
-                       $conts =~ s/,$//;
-                       my @vals = split(/,/, $conts);
-                       my ($pfx, $pfx1);
-                       for my $e (@vals) {
-                               if (!defined($pfx)) {
-                                       $pfx1 = $pfx = ($e =~ /^([A-Z]+_)/) ? 
$1 : "";
-                               } elsif (length($pfx)) {
-                                       $pfx = "" if ((($e =~ /^([A-Z]+_)/) ? 
$1 : "") ne $pfx);
-                               }
-                       }
-                       my $bit = 1;
-                       my $bitn = 0;
-                       my (@names, @nameos);
-                       my $nameo = 0;
-                       for my $e (@vals) {
-                               my $bits = ($e =~ s/\((\d+)\)$//) ? $1 : 1;
-                               my $n = substr($e, length($pfx));
-                               if ($bits != 1) {
-                                       die("Unsupported field size $bits\n") 
if ($bits != 2);
-                                       print "#define $e(b) ($bit << (b))\n";
-                                       push @names, "F-".$n, "N-".$n;
-                                       my $nl = length($n) + 3;
-                                       push @nameos, $nameo, $nameo + $nl;
-                                       $nameo += $nl * 2;
-                               } else {
-                                       print "#define $e $bit\n";
-                                       push @names, $n;
-                                       push @nameos, $nameo;
-                                       $nameo += length($n) + 1;
-                               }
-                               $bit <<= $bits;
-                               $bitn += $bits;
-                       }
-                       if (length($pfx)) {
-                               print "#define ${pfx}_NUM_BITS $bitn\n";
-                       }
-                       if (length($pfx1)) {
-                               print "#define ${pfx1}_STRINGS \"".join("\\0", 
@names)."\"\n";
-                               print "#define ${pfx1}_OFFSETS ".join(", ", 
@nameos)."\n";
-                       }
-                       print "\n";
-                       $in_enum = 0;
-               } else {
-                       $conts .= $_;
-               }
-       } else {
-               if (/^BIT_ENUM\($/) {
-                       $conts = "";
-                       $in_enum = 1;
-               }
-       }
-}
diff --git a/src/common.h b/src/common.h
index 9c44bce..38521b6 100644
--- a/src/common.h
+++ b/src/common.h
@@ -21,8 +21,6 @@
 #include <string.h>
 #include <time.h>
 
-#include "common_enum.h"
-
 typedef unsigned char uchar;
 typedef unsigned short ushort;
 typedef unsigned int uint;
@@ -43,10 +41,55 @@ typedef unsigned long ulong;
 #define shifted_bit(in, from, to) \
        ((int)(((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / 
from : 1)) & to))
 
-#define BIT_ENUM(...)
+#define BIT_ENUM_VAL(name) \
+       name, \
+       name##_dummy = 2 * name - 1,
+
+#define DEFINE_BIT_ENUM(list) \
+       enum list { \
+               list##_dummy, \
+               list(BIT_ENUM_VAL) \
+       };
+
+#define PFX_BIT_ENUM_VAL(pfx, name) \
+       pfx##_##name, \
+       pfx##_##name##_dummy = 2 * pfx##_##name - 1,
+
+#define PFX_BIT_ENUM_NUM(pfx, name) \
+       pfx##_##name##_bit,
+
+#define DEFINE_PFX_BIT_ENUM(list) \
+       enum list { \
+               list##_dummy, \
+               list(PFX_BIT_ENUM_VAL) \
+       }; \
+       enum { \
+               list(PFX_BIT_ENUM_NUM) \
+               list##_num_bits \
+       };
+
+#define BIT_ENUM_STR(pfx, name) \
+       stringify(name) "\0"
+
+#define BIT_ENUM_STR_OFF(pfx, name) \
+       name##_str_off, \
+       name##_str_off_dummy = name##_str_off + sizeof(stringify(name)) - 1,
+
+#define GET_BIT_ENUM_STR_OFF(pfx, name) \
+       name##_str_off,
 
-#define static_assert_bits(pfx, type, field) \
-       static_assert( pfx##__NUM_BITS <= sizeof(((type){ 0 }).field) * 8, \
+#define PFX_BIT_ENUM_STR(pfx, name) \
+       stringify(pfx) "_" stringify(name) "\0"
+
+#define PFX_BIT_ENUM_STR_OFF(pfx, name) \
+       pfx##_##name##_str_off, \
+       pfx##_##name##_str_end = pfx##_##name##_str_off + sizeof(stringify(pfx) 
"_" stringify(name)) - 1,
+
+#define GET_PFX_BIT_ENUM_STR_OFF(pfx, name) \
+       pfx##_##name##_str_off,
+
+#define static_assert_bits(list, type, field) \
+       static_assert( list##_num_bits <= sizeof(((type){ 0 }).field) * 8, \
                       stringify(type) "::" stringify(field) " is too small" )
 
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
@@ -100,30 +143,32 @@ enum {
        VERBOSE,
 };
 
-BIT_ENUM(
-       DEBUG_MAILDIR,
-       DEBUG_NET,
-       DEBUG_NET_ALL,
-       DEBUG_SYNC,
-       DEBUG_MAIN,
-       DEBUG_DRV,
-       DEBUG_DRV_ALL,
-
-       DEBUG_CRASH,
-
-       PROGRESS,
-
-       DRYRUN,
-
-       EXT_EXIT,
-
-       ZERODELAY,
-       KEEPJOURNAL,
-       FORCEJOURNAL,
-       FORCEASYNC(2),
-       FAKEEXPUNGE,
-       FAKEDUMBSTORE,
-)
+#define options_enum(fn) \
+       fn(DEBUG_MAILDIR) \
+       fn(DEBUG_NET) \
+       fn(DEBUG_NET_ALL) \
+       fn(DEBUG_SYNC) \
+       fn(DEBUG_MAIN) \
+       fn(DEBUG_DRV) \
+       fn(DEBUG_DRV_ALL) \
+       \
+       fn(DEBUG_CRASH) \
+       \
+       fn(PROGRESS) \
+       \
+       fn(DRYRUN) \
+       \
+       fn(EXT_EXIT) \
+       \
+       fn(ZERODELAY) \
+       fn(KEEPJOURNAL) \
+       fn(FORCEJOURNAL) \
+       fn(FORCEASYNC_F) \
+       fn(FORCEASYNC_N) \
+       fn(FAKEEXPUNGE) \
+       fn(FAKEDUMBSTORE)
+DEFINE_BIT_ENUM(options_enum)
+#define FORCEASYNC(b) (FORCEASYNC_F << (b))
 
 #define DEBUG_ANY (DEBUG_MAILDIR | DEBUG_NET | DEBUG_SYNC | DEBUG_MAIN | 
DEBUG_DRV)
 #define DEBUG_ALL (DEBUG_ANY | DEBUG_CRASH)
@@ -209,34 +254,38 @@ time_t timegm( struct tm *tm );
 
 void fmt_bits( uint bits, uint num_bits, const char *bit_str, const int 
*bit_off, char *buf );
 
-#define BIT_FORMATTER_RET(name, pfx) \
-       struct name##_str { char str[sizeof(pfx##__STRINGS)]; };
+#define BIT_FORMATTER_RET(name, list, fn) \
+       enum { list(fn##_OFF) name##_str_len }; \
+       struct name##_str { char str[name##_str_len]; };
 
 #define BIT_FORMATTER_PROTO(name, storage) \
        storage struct name##_str ATTR_OPTIMIZE  /* force RVO */ \
        fmt_##name( uint bits )
 
-#define BIT_FORMATTER_IMPL(name, pfx, storage) \
+#define BIT_FORMATTER_IMPL(name, list, fn, storage) \
        BIT_FORMATTER_PROTO(name, storage) \
        { \
-               static const char strings[] = pfx##__STRINGS; \
-               static const int offsets[] = { pfx##__OFFSETS }; \
+               static const char strings[] = list(fn); \
+               static const int offsets[] = { list(GET_##fn##_OFF) }; \
                \
                struct name##_str buf; \
                fmt_bits( bits, as(offsets), strings, offsets, buf.str ); \
                return buf; \
        }
 
-#define BIT_FORMATTER_FUNCTION(name, pfx) \
-       BIT_FORMATTER_RET(name, pfx) \
-       BIT_FORMATTER_IMPL(name, pfx, static)
+// Note that this one uses enum labels without prefix ...
+#define BIT_FORMATTER_FUNCTION(name, list) \
+       BIT_FORMATTER_RET(name, list, BIT_ENUM_STR) \
+       BIT_FORMATTER_IMPL(name, list, BIT_ENUM_STR, static)
 
-#define DECL_BIT_FORMATTER_FUNCTION(name, pfx) \
-       BIT_FORMATTER_RET(name, pfx) \
+// ... while these ones use enum labels with prefix - this
+// is not fundamental, but simply because of the use cases.
+#define DECL_BIT_FORMATTER_FUNCTION(name, list) \
+       BIT_FORMATTER_RET(name, list, PFX_BIT_ENUM_STR) \
        BIT_FORMATTER_PROTO(name, );
 
-#define DEF_BIT_FORMATTER_FUNCTION(name, pfx) \
-       BIT_FORMATTER_IMPL(name, pfx, )
+#define DEF_BIT_FORMATTER_FUNCTION(name, list) \
+       BIT_FORMATTER_IMPL(name, list, PFX_BIT_ENUM_STR, )
 
 void *nfmalloc( size_t sz );
 void *nfzalloc( size_t sz );
diff --git a/src/config.c b/src/config.c
index 456bd47..4ff389e 100644
--- a/src/config.c
+++ b/src/config.c
@@ -22,7 +22,7 @@ char FieldDelimiter = ';';
 char FieldDelimiter = ':';
 #endif
 
-DEF_BIT_FORMATTER_FUNCTION(ops, OP)
+DEF_BIT_FORMATTER_FUNCTION(ops, sync_op_enum)
 
 char *
 expand_strdup( const char *s, const conffile_t *cfile )
diff --git a/src/driver.h b/src/driver.h
index f7c5b95..fde8908 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -9,7 +9,6 @@
 #define DRIVER_H
 
 #include "config.h"
-#include "driver_enum.h"
 
 typedef struct driver driver_t;
 
@@ -36,32 +35,32 @@ extern store_conf_t *stores;
 /* For message->flags */
 // Keep the MESSAGE_FLAGS in sync (grep that)!
 /* The order is according to alphabetical maildir flag sort */
-BIT_ENUM(
-       F_DRAFT,      // Draft
-       F_FLAGGED,    // Flagged
-       F_FORWARDED,  // Passed
-       F_ANSWERED,   // Replied
-       F_SEEN,       // Seen
-       F_DELETED,    // Trashed
-)
-
-extern const char MsgFlags[F__NUM_BITS];
-typedef struct { char str[F__NUM_BITS + 1]; } flag_str_t;
+#define msg_flags_enum(fn) \
+       fn(F, DRAFT)      /* Draft    */ \
+       fn(F, FLAGGED)    /* Flagged  */ \
+       fn(F, FORWARDED)  /* Passed   */ \
+       fn(F, ANSWERED)   /* Replied  */ \
+       fn(F, SEEN)       /* Seen     */ \
+       fn(F, DELETED)    /* Trashed  */
+DEFINE_PFX_BIT_ENUM(msg_flags_enum)
+
+extern const char MsgFlags[msg_flags_enum_num_bits];
+typedef struct { char str[msg_flags_enum_num_bits + 1]; } flag_str_t;
 flag_str_t ATTR_OPTIMIZE /* force RVO */ fmt_flags( uchar flags );
 flag_str_t ATTR_OPTIMIZE /* force RVO */ fmt_lone_flags( uchar flags );
 
 /* For message->status */
-BIT_ENUM(
-       M_RECENT,   // unsyncable flag; maildir_*() depend on this being bit 0
-       M_DEAD,     // expunged
-       M_EXPUNGE,  // for driver_t->close_box()
-       M_FLAGS,    // flags are valid
-       // The following are only for IMAP FETCH response parsing
-       M_DATE,
-       M_SIZE,
-       M_BODY,
-       M_HEADER,
-)
+#define msg_sts_enum(fn) \
+       fn(M, RECENT)   /* unsyncable flag; maildir_*() depend on this being 
bit 0 */ \
+       fn(M, DEAD)     /* expunged */ \
+       fn(M, EXPUNGE)  /* for driver_t->close_box() */ \
+       fn(M, FLAGS)    /* flags are valid */ \
+       /* The following are only for IMAP FETCH response parsing */ \
+       fn(M, DATE) \
+       fn(M, SIZE) \
+       fn(M, BODY) \
+       fn(M, HEADER)
+DEFINE_PFX_BIT_ENUM(msg_sts_enum)
 
 #define TUIDL 12
 
@@ -79,29 +78,29 @@ typedef struct message {
        MESSAGE(struct message)
 } message_t;
 
-static_assert_bits(F, message_t, flags);
-static_assert_bits(M, message_t, status);
+static_assert_bits(msg_flags_enum, message_t, flags);
+static_assert_bits(msg_sts_enum, message_t, status);
 
 // For driver_t->prepare_load_box(), which may amend the passed flags.
 // The drivers don't use the first three, but may set them if loading the
 // particular range is required to handle some other flag; note that these
 // ranges may overlap.
-BIT_ENUM(
-       OPEN_PAIRED,      // Paired messages *in* this store.
-       OPEN_OLD,         // Messages that should be already propagated *from* 
this store.
-       OPEN_NEW,         // Messages (possibly) not yet propagated *from* this 
store.
-       OPEN_FIND,
-       OPEN_FLAGS,       // Note that fetch_msg() gets the flags regardless.
-       OPEN_OLD_SIZE,
-       OPEN_NEW_SIZE,
-       OPEN_PAIRED_IDS,
-       OPEN_APPEND,
-       OPEN_SETFLAGS,
-       OPEN_EXPUNGE,
-       // Expunge only deleted messages we know about. Relies on 
OPEN_{OLD,NEW,FLAGS}
-       // being set externally. The driver may unset it if it can't handle it.
-       OPEN_UID_EXPUNGE,
-)
+#define open_flags_enum(fn) \
+       fn(OPEN, PAIRED)        /* Paired messages *in* this store. */ \
+       fn(OPEN, OLD)           /* Messages that should be already propagated 
*from* this store. */ \
+       fn(OPEN, NEW)           /* Messages (possibly) not yet propagated 
*from* this store. */ \
+       fn(OPEN, FIND) \
+       fn(OPEN, FLAGS)         /* Note that fetch_msg() gets the flags 
regardless. */ \
+       fn(OPEN, OLD_SIZE) \
+       fn(OPEN, NEW_SIZE) \
+       fn(OPEN, PAIRED_IDS) \
+       fn(OPEN, APPEND) \
+       fn(OPEN, SETFLAGS) \
+       fn(OPEN, EXPUNGE) \
+       /* Expunge only deleted messages we know about. Relies on 
OPEN_{OLD,NEW,FLAGS} */ \
+       /* being set externally. The driver may unset it if it can't handle it. 
*/ \
+       fn(OPEN, UID_EXPUNGE)
+DEFINE_PFX_BIT_ENUM(open_flags_enum)
 
 #define UIDVAL_BAD ((uint)-1)
 
@@ -122,7 +121,7 @@ typedef struct {
        uchar flags;
 } msg_data_t;
 
-static_assert_bits(F, msg_data_t, flags);
+static_assert_bits(msg_flags_enum, msg_data_t, flags);
 
 #define DRV_OK          0
 /* Message went missing, or mailbox is full, etc. */
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 5b67535..cbf5804 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3110,7 +3110,7 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, 
uint finduid, uint pairu
                                if (i != j)
                                        bl += sprintf( buf + bl, ":%u", 
excs.data[i] );
                        }
-                       imap_submit_load( ctx, buf, shifted_bit( ctx->opts, 
OPEN_PAIRED_IDS, WantMsgids ), sts );
+                       imap_submit_load( ctx, buf, shifted_bit( ctx->opts, 
(int)OPEN_PAIRED_IDS, WantMsgids ), sts );
                }
                if (maxuid == UINT_MAX)
                        maxuid = ctx->uidnext - 1;
diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index ffe2e06..193f511 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -8,7 +8,7 @@
 
 #include "driver.h"
 
-BIT_FORMATTER_FUNCTION(opts, OPEN)
+BIT_FORMATTER_FUNCTION(opts, open_flags_enum)
 
 typedef struct gen_cmd gen_cmd_t;
 
diff --git a/src/sync.c b/src/sync.c
index 7f95e85..600b7af 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -6,7 +6,6 @@
  */
 
 #include "sync_p.h"
-#include "sync_c_enum.h"
 
 channel_conf_t global_conf;
 channel_conf_t *channels;
@@ -45,24 +44,24 @@ static int check_cancel( sync_vars_t *svars );
    cleanup: close(F) & close(N)
 */
 
-BIT_ENUM(
-       ST_PRESENT,
-       ST_CONFIRMED,
-       ST_SELECTED,
-       ST_FIND_OLD,
-       ST_LOADED,
-       ST_SENT_FLAGS,
-       ST_SENDING_NEW,
-       ST_SENT_NEW,
-       ST_FIND_NEW,
-       ST_FOUND_NEW,
-       ST_SENT_TRASH,
-       ST_TRASH_BAD,
-       ST_CLOSING,
-       ST_CLOSED,
-       ST_SENT_CANCEL,
-       ST_CANCELED,
-)
+#define sync_sts_enum(fn) \
+       fn(ST, PRESENT) \
+       fn(ST, CONFIRMED) \
+       fn(ST, SELECTED) \
+       fn(ST, FIND_OLD) \
+       fn(ST, LOADED) \
+       fn(ST, SENT_FLAGS) \
+       fn(ST, SENDING_NEW) \
+       fn(ST, SENT_NEW) \
+       fn(ST, FIND_NEW) \
+       fn(ST, FOUND_NEW) \
+       fn(ST, SENT_TRASH) \
+       fn(ST, TRASH_BAD) \
+       fn(ST, CLOSING) \
+       fn(ST, CLOSED) \
+       fn(ST, SENT_CANCEL) \
+       fn(ST, CANCELED)
+DEFINE_PFX_BIT_ENUM(sync_sts_enum)
 
 static uchar
 sanitize_flags( uchar tflags, sync_vars_t *svars, int t )
diff --git a/src/sync.h b/src/sync.h
index ced07e7..78f952a 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -9,44 +9,43 @@
 #define SYNC_H
 
 #include "driver.h"
-#include "sync_enum.h"
 
 #define F 0  // far side
 #define N 1  // near side
 
-BIT_ENUM(
-       OP_NEW,
-       OP_OLD,
-       OP_UPGRADE,
-       OP_GONE,
-       OP_FLAGS,
-       OP_EXPUNGE,
-       OP_EXPUNGE_SOLO,
-       OP_CREATE,
-       OP_REMOVE,
-
-       XOP_PUSH,
-       XOP_PULL,
-       XOP_HAVE_TYPE,  // Aka mode; have at least one of dir and type (see 
below)
-       // The following must all have the same bit shift from the 
corresponding OP_* flags.
-       XOP_HAVE_EXPUNGE,
-       XOP_HAVE_EXPUNGE_SOLO,
-       XOP_HAVE_CREATE,
-       XOP_HAVE_REMOVE,
-       // ... until here.
-       XOP_TYPE_NOOP,
-       // ... and here again from scratch.
-       XOP_EXPUNGE_NOOP,
-       XOP_EXPUNGE_SOLO_NOOP,
-       XOP_CREATE_NOOP,
-       XOP_REMOVE_NOOP,
-)
+#define sync_op_enum(fn) \
+       fn(OP, NEW) \
+       fn(OP, OLD) \
+       fn(OP, UPGRADE) \
+       fn(OP, GONE) \
+       fn(OP, FLAGS) \
+       fn(OP, EXPUNGE) \
+       fn(OP, EXPUNGE_SOLO) \
+       fn(OP, CREATE) \
+       fn(OP, REMOVE) \
+       \
+       fn(XOP, PUSH) \
+       fn(XOP, PULL) \
+       fn(XOP, HAVE_TYPE)  /* Aka mode; have at least one of dir and type (see 
below) */ \
+       /* The following must all have the same bit shift from the 
corresponding OP_* flags. */ \
+       fn(XOP, HAVE_EXPUNGE) \
+       fn(XOP, HAVE_EXPUNGE_SOLO) \
+       fn(XOP, HAVE_CREATE) \
+       fn(XOP, HAVE_REMOVE) \
+       /* ... until here. */ \
+       fn(XOP, TYPE_NOOP) \
+       /* ... and here again from scratch. */ \
+       fn(XOP, EXPUNGE_NOOP) \
+       fn(XOP, EXPUNGE_SOLO_NOOP) \
+       fn(XOP, CREATE_NOOP) \
+       fn(XOP, REMOVE_NOOP)
+DEFINE_PFX_BIT_ENUM(sync_op_enum)
 
 #define OP_DFLT_TYPE (OP_NEW | OP_UPGRADE | OP_GONE | OP_FLAGS)
 #define OP_MASK_TYPE (OP_DFLT_TYPE | OP_OLD)  // Asserted in the target side 
ops
 #define XOP_MASK_DIR (XOP_PUSH | XOP_PULL)
 
-DECL_BIT_FORMATTER_FUNCTION(ops, OP)
+DECL_BIT_FORMATTER_FUNCTION(ops, sync_op_enum)
 
 typedef struct channel_conf {
        struct channel_conf *next;
diff --git a/src/sync_p.h b/src/sync_p.h
index 1c9e7e4..4a13fc1 100644
--- a/src/sync_p.h
+++ b/src/sync_p.h
@@ -7,23 +7,28 @@
 #define DEBUG_FLAG DEBUG_SYNC
 
 #include "sync.h"
-#include "sync_p_enum.h"
-
-BIT_ENUM(
-       S_DEAD,         // ephemeral: the entry was killed and should be ignored
-       S_EXPIRE,       // the entry is being expired (expire-side message 
removal scheduled)
-       S_EXPIRED,      // the entry is expired (expire-side message removal 
confirmed)
-       S_NEXPIRE,      // temporary: new expiration state
-       S_PENDING,      // the entry is new and awaits propagation (possibly a 
retry)
-       S_DUMMY(2),     // f/n message is only a placeholder
-       S_SKIPPED,      // pre-1.4 legacy: the entry was not propagated 
(message is too big)
-       S_GONE(2),      // ephemeral: f/n message has been expunged
-       S_DEL(2),       // ephemeral: f/n message would be subject to 
non-selective expunge
-       S_DELETE,       // ephemeral: flags propagation is a deletion
-       S_UPGRADE,      // ephemeral: upgrading placeholder, do not apply 
MaxSize
-       S_PURGE,        // ephemeral: placeholder is being nuked
-       S_PURGED,       // ephemeral: placeholder was nuked
-)
+
+#define srec_sts_enum(fn) \
+       fn(S, DEAD)         /* ephemeral: the entry was killed and should be 
ignored */ \
+       fn(S, EXPIRE)       /* the entry is being expired (expire-side message 
removal scheduled) */ \
+       fn(S, EXPIRED)      /* the entry is expired (expire-side message 
removal confirmed) */ \
+       fn(S, NEXPIRE)      /* temporary: new expiration state */ \
+       fn(S, PENDING)      /* the entry is new and awaits propagation 
(possibly a retry) */ \
+       fn(S, DUMMY_F)      /* f/n message is only a placeholder */ \
+       fn(S, DUMMY_N)      \
+       fn(S, SKIPPED)      /* pre-1.4 legacy: the entry was not propagated 
(message is too big) */ \
+       fn(S, GONE_F)       /* ephemeral: f/n message has been expunged */ \
+       fn(S, GONE_N)       \
+       fn(S, DEL_F)        /* ephemeral: f/n message would be subject to 
non-selective expunge */ \
+       fn(S, DEL_N)        \
+       fn(S, DELETE)       /* ephemeral: flags propagation is a deletion */ \
+       fn(S, UPGRADE)      /* ephemeral: upgrading placeholder, do not apply 
MaxSize */ \
+       fn(S, PURGE)        /* ephemeral: placeholder is being nuked */ \
+       fn(S, PURGED)       /* ephemeral: placeholder was nuked */
+DEFINE_PFX_BIT_ENUM(srec_sts_enum)
+#define S_DUMMY(b) (S_DUMMY_F << (b))
+#define S_GONE(b) (S_GONE_F << (b))
+#define S_DEL(b) (S_DEL_F << (b))
 
 // This is the persistent status of the sync record, with regard to the 
journal.
 #define S_LOGGED (S_EXPIRE | S_EXPIRED | S_PENDING | S_DUMMY(F) | S_DUMMY(N) | 
S_SKIPPED)
@@ -38,8 +43,8 @@ typedef struct sync_rec {
        char tuid[TUIDL];
 } sync_rec_t;
 
-static_assert_bits(F, sync_rec_t, flags);
-static_assert_bits(S, sync_rec_t, status);
+static_assert_bits(msg_flags_enum, sync_rec_t, flags);
+static_assert_bits(srec_sts_enum, sync_rec_t, status);
 
 typedef struct {
        int t[2];
diff --git a/src/sync_state.c b/src/sync_state.c
index 5567f10..d499f85 100644
--- a/src/sync_state.c
+++ b/src/sync_state.c
@@ -17,7 +17,7 @@
 
 const char *str_fn[] = { "far side", "near side" }, *str_hl[] = { "push", 
"pull" };
 
-BIT_FORMATTER_FUNCTION(sts, S)
+BIT_FORMATTER_FUNCTION(sts, srec_sts_enum)
 
 static char *
 clean_strdup( const char *s )


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to