commit 6a78e2c5f61fdc1ec18a87f05f800d22ca59dfa6
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Tue May 31 14:05:28 2022 +0200

    automate enumeration of power-of-two #defines
    
    this is a lot more legible, and makes it possible to insert values in
    the middle without churn.
    
    i didn't find a way to do this with the pre-processor, so we now have
    another code generator.
    
    we now use the $< make variable, which requires gmake on netbsd < 9.0,
    and possibly other systems with an ancient make.

 src/.gitignore      |  1 +
 src/Makefile.am     | 26 ++++++++++++++++++--
 src/bit_enum_gen.pl | 55 ++++++++++++++++++++++++++++++++++++++++++
 src/common.h        | 33 ++++++++++++++++----------
 src/driver.h        | 58 +++++++++++++++++++++++++--------------------
 src/drv_maildir.c   |  2 +-
 src/sync.c          | 36 +++++++++++++++-------------
 src/sync.h          | 37 ++++++++++++++++-------------
 src/sync_p.h        | 27 ++++++++++++---------
 src/sync_state.c    |  2 +-
 10 files changed, 191 insertions(+), 86 deletions(-)

diff --git a/src/.gitignore b/src/.gitignore
index 116456f9..15e76dbc 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,4 @@
+/*_enum.h
 /drv_proxy.inc
 /mbsync
 /mdconvert
diff --git a/src/Makefile.am b/src/Makefile.am
index e06005da..1df4cca1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,28 @@ 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
@@ -36,6 +58,6 @@ EXTRA_PROGRAMS = tst_timers
 exampledir = $(docdir)/examples
 example_DATA = mbsyncrc.sample
 
-EXTRA_DIST = drv_proxy_gen.pl run-tests.pl $(example_DATA) $(man_MANS)
+EXTRA_DIST = bit_enum_gen.pl drv_proxy_gen.pl run-tests.pl $(example_DATA) 
$(man_MANS)
 
-CLEANFILES = drv_proxy.inc
+CLEANFILES = *_enum.h drv_proxy.inc
diff --git a/src/bit_enum_gen.pl b/src/bit_enum_gen.pl
new file mode 100755
index 00000000..9bf0e6a0
--- /dev/null
+++ b/src/bit_enum_gen.pl
@@ -0,0 +1,55 @@
+#!/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;
+                       for my $e (@vals) {
+                               if (!defined($pfx)) {
+                                       $pfx = ($e =~ /^([A-Z]+_)/) ? $1 : "";
+                               } elsif (length($pfx)) {
+                                       $pfx = "" if ((($e =~ /^([A-Z]+_)/) ? 
$1 : "") ne $pfx);
+                               }
+                       }
+                       my $bit = 1;
+                       my $bitn = 0;
+                       for my $e (@vals) {
+                               my $bits = ($e =~ s/\((\d+)\)$//) ? $1 : 1;
+                               if ($bits != 1) {
+                                       print "#define $e(b) ($bit << (b))\n";
+                               } else {
+                                       print "#define $e $bit\n";
+                               }
+                               $bit <<= $bits;
+                               $bitn += $bits;
+                       }
+                       if (length($pfx)) {
+                               print "#define ${pfx}_NUM_BITS $bitn\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 9ec6b369..112b735a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -21,6 +21,8 @@
 #include <string.h>
 #include <time.h>
 
+#include "common_enum.h"
+
 typedef unsigned char uchar;
 typedef unsigned short ushort;
 typedef unsigned int uint;
@@ -41,6 +43,8 @@ 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(...)
+
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
 # define ATTR_UNUSED __attribute__((unused))
 # define ATTR_NORETURN __attribute__((noreturn))
@@ -90,18 +94,23 @@ enum {
        VERBOSE,
 };
 
-#define DEBUG_CRASH     0x01
-#define DEBUG_MAILDIR   0x02
-#define DEBUG_NET       0x04
-#define DEBUG_NET_ALL   0x08
-#define DEBUG_SYNC      0x10
-#define DEBUG_MAIN      0x20
-#define DEBUG_DRV       0x40
-#define DEBUG_DRV_ALL   0x80
-#define PROGRESS        0x400
-#define KEEPJOURNAL     0x1000
-#define ZERODELAY       0x2000
-#define FORCEASYNC      0x4000
+BIT_ENUM(
+       DEBUG_MAILDIR,
+       DEBUG_NET,
+       DEBUG_NET_ALL,
+       DEBUG_SYNC,
+       DEBUG_MAIN,
+       DEBUG_DRV,
+       DEBUG_DRV_ALL,
+
+       DEBUG_CRASH,
+
+       PROGRESS,
+
+       ZERODELAY,
+       KEEPJOURNAL,
+       FORCEASYNC,
+)
 
 #define DEBUG_ANY (DEBUG_MAILDIR | DEBUG_NET | DEBUG_SYNC | DEBUG_MAIN | 
DEBUG_DRV)
 #define DEBUG_ALL (DEBUG_ANY | DEBUG_CRASH)
diff --git a/src/driver.h b/src/driver.h
index edb94040..1f9749f7 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -9,6 +9,7 @@
 #define DRIVER_H
 
 #include "config.h"
+#include "driver_enum.h"
 
 typedef struct driver driver_t;
 
@@ -33,26 +34,29 @@ typedef struct store_conf {
 /* For message->flags */
 // Keep the MESSAGE_FLAGS in sync (grep that)!
 /* The order is according to alphabetical maildir flag sort */
-#define F_DRAFT             (1<<0) /* Draft */
-#define F_FLAGGED    (1<<1) /* Flagged */
-#define F_FORWARDED  (1<<2) /* Passed */
-#define F_ANSWERED   (1<<3) /* Replied */
-#define F_SEEN       (1<<4) /* Seen */
-#define F_DELETED    (1<<5) /* Trashed */
-#define NUM_FLAGS 6
-
-extern const char MsgFlags[NUM_FLAGS];
+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];
 void make_flags( uchar flags, char *buf );
 
 /* For message->status */
-#define M_RECENT       (1<<0) /* unsyncable flag; maildir_* depend on this 
being 1<<0 */
-#define M_DEAD         (1<<1) /* expunged */
-#define M_FLAGS        (1<<2) /* flags fetched */
-// The following are only for IMAP FETCH response parsing
-#define M_DATE         (1<<3)
-#define M_SIZE         (1<<4)
-#define M_BODY         (1<<5)
-#define M_HEADER       (1<<6)
+BIT_ENUM(
+       M_RECENT,   // unsyncable flag; maildir_*() depend on this being bit 0
+       M_DEAD,     // expunged
+       M_FLAGS,    // flags are valid
+       // The following are only for IMAP FETCH response parsing
+       M_DATE,
+       M_SIZE,
+       M_BODY,
+       M_HEADER,
+)
 
 #define TUIDL 12
 
@@ -74,15 +78,17 @@ typedef struct message {
 // The drivers don't use the first two, but may set them if loading the
 // particular range is required to handle some other flag; note that these
 // ranges may overlap.
-#define OPEN_OLD        (1<<0)  // Paired messages *in* this store.
-#define OPEN_NEW        (1<<1)  // Messages (possibly) not yet propagated 
*from* this store.
-#define OPEN_FLAGS      (1<<2)  // Note that fetch_msg() gets the flags 
regardless.
-#define OPEN_NEW_SIZE   (1<<4)
-#define OPEN_EXPUNGE    (1<<5)
-#define OPEN_SETFLAGS   (1<<6)
-#define OPEN_APPEND     (1<<7)
-#define OPEN_FIND       (1<<8)
-#define OPEN_OLD_IDS    (1<<9)
+BIT_ENUM(
+       OPEN_OLD,         // Paired messages *in* 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_NEW_SIZE,
+       OPEN_OLD_IDS,
+       OPEN_APPEND,
+       OPEN_SETFLAGS,
+       OPEN_EXPUNGE,
+)
 
 #define UIDVAL_BAD ((uint)-1)
 
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index c1de4dcb..fbef3a87 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1565,7 +1565,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
        const char *box;
        int ret, fd, bl;
        uint uid;
-       char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], 
base[128];
+       char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[as(MsgFlags) + 
3], base[128];
 
        bl = nfsnprintf( base, sizeof(base), "%lld.%d_%d.%s", (long long)time( 
NULL ), Pid, ++MaildirCount, Hostname );
        if (!to_trash) {
diff --git a/src/sync.c b/src/sync.c
index 50bf56dd..99b852a5 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -6,6 +6,7 @@
  */
 
 #include "sync_p.h"
+#include "sync_c_enum.h"
 
 channel_conf_t global_conf;
 channel_conf_t *channels;
@@ -43,23 +44,24 @@ static int check_cancel( sync_vars_t *svars );
    cleanup: close(F) & close(N)
 */
 
-#define ST_LOADED          (1<<0)
-#define ST_FIND_OLD        (1<<1)
-#define ST_SENT_NEW        (1<<2)
-#define ST_FIND_NEW        (1<<3)
-#define ST_FOUND_NEW       (1<<4)
-#define ST_SENT_FLAGS      (1<<5)
-#define ST_SENT_TRASH      (1<<6)
-#define ST_CLOSED          (1<<7)
-#define ST_SENT_CANCEL     (1<<8)
-#define ST_CANCELED        (1<<9)
-#define ST_SELECTED        (1<<10)
-#define ST_DID_EXPUNGE     (1<<11)
-#define ST_CLOSING         (1<<12)
-#define ST_CONFIRMED       (1<<13)
-#define ST_PRESENT         (1<<14)
-#define ST_SENDING_NEW     (1<<15)
-
+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_CLOSING,
+       ST_CLOSED,
+       ST_DID_EXPUNGE,
+       ST_SENT_CANCEL,
+       ST_CANCELED,
+)
 
 static uchar
 sanitize_flags( uchar tflags, sync_vars_t *svars, int t )
diff --git a/src/sync.h b/src/sync.h
index d0916098..af31ad3b 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -9,26 +9,31 @@
 #define SYNC_H
 
 #include "driver.h"
+#include "sync_enum.h"
 
 #define F 0  // far side
 #define N 1  // near side
 
-#define OP_NEW             (1<<0)
-#define OP_RENEW           (1<<1)
-#define OP_DELETE          (1<<2)
-#define OP_FLAGS           (1<<3)
-#define  OP_MASK_TYPE      (OP_NEW|OP_RENEW|OP_DELETE|OP_FLAGS) /* asserted in 
the target ops */
-#define OP_EXPUNGE         (1<<4)
-#define OP_CREATE          (1<<5)
-#define OP_REMOVE          (1<<6)
-#define XOP_PUSH           (1<<8)
-#define XOP_PULL           (1<<9)
-#define  XOP_MASK_DIR      (XOP_PUSH|XOP_PULL)
-#define XOP_HAVE_TYPE      (1<<10)  // Aka mode; at least one of dir and type
-// The following must all have the same bit shift from the corresponding OP_* 
flags.
-#define XOP_HAVE_EXPUNGE   (1<<11)
-#define XOP_HAVE_CREATE    (1<<12)
-#define XOP_HAVE_REMOVE    (1<<13)
+BIT_ENUM(
+       OP_NEW,
+       OP_RENEW,
+       OP_DELETE,
+       OP_FLAGS,
+       OP_EXPUNGE,
+       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_CREATE,
+       XOP_HAVE_REMOVE,
+)
+
+#define OP_MASK_TYPE (OP_NEW | OP_RENEW | OP_DELETE | OP_FLAGS)  // Asserted 
in the target side ops
+#define XOP_MASK_DIR (XOP_PUSH | XOP_PULL)
 
 typedef struct channel_conf {
        struct channel_conf *next;
diff --git a/src/sync_p.h b/src/sync_p.h
index 07eefcbf..e6234757 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"
 
 // This is the (mostly) persistent status of the sync record.
 // Most of these bits are actually mutually exclusive. It is a
 // bitfield to allow for easy testing for multiple states.
-#define S_EXPIRE       (1<<0)  // the entry is being expired (near side 
message removal scheduled)
-#define S_EXPIRED      (1<<1)  // the entry is expired (near side message 
removal confirmed)
-#define S_PENDING      (1<<2)  // the entry is new and awaits propagation 
(possibly a retry)
-#define S_DUMMY(fn)    (1<<(3+(fn)))  // f/n message is only a placeholder
-#define S_SKIPPED      (1<<5)  // pre-1.4 legacy: the entry was not propagated 
(message is too big)
-#define S_DEAD         (1<<7)  // ephemeral: the entry was killed and should 
be ignored
+BIT_ENUM(
+       S_DEAD,         // ephemeral: the entry was killed and should be ignored
+       S_EXPIRE,       // the entry is being expired (near side message 
removal scheduled)
+       S_EXPIRED,      // the entry is expired (near side message removal 
confirmed)
+       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)
+)
 
 // Ephemeral working set.
-#define W_NEXPIRE      (1<<0)  // temporary: new expiration state
-#define W_DELETE       (1<<1)  // ephemeral: flags propagation is a deletion
-#define W_DEL(fn)      (1<<(2+(fn)))  // ephemeral: f/n message would be 
subject to expunge
-#define W_UPGRADE      (1<<4)  // ephemeral: upgrading placeholder, do not 
apply MaxSize
-#define W_PURGE        (1<<5)  // ephemeral: placeholder is being nuked
+BIT_ENUM(
+       W_NEXPIRE,      // temporary: new expiration state
+       W_DELETE,       // ephemeral: flags propagation is a deletion
+       W_DEL(2),       // ephemeral: f/n message would be subject to expunge
+       W_UPGRADE,      // ephemeral: upgrading placeholder, do not apply 
MaxSize
+       W_PURGE,        // ephemeral: placeholder is being nuked
+)
 
 typedef struct sync_rec {
        struct sync_rec *next;
diff --git a/src/sync_state.c b/src/sync_state.c
index 0b0cfd65..d9917ec6 100644
--- a/src/sync_state.c
+++ b/src/sync_state.c
@@ -13,7 +13,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#define JOURNAL_VERSION "4"
+#define JOURNAL_VERSION "5"
 
 const char *str_fn[] = { "far side", "near side" }, *str_hl[] = { "push", 
"pull" };
 


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

Reply via email to