From ee832951e2bc2030abe49b1436760a597bd55382 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Jul 2023 12:04:13 +0200 Subject: [PATCH] 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(-) delete mode 100755 src/bit_enum_gen.pl 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 -# 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 #include -#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 )