Browse Source

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.
master
Oswald Buddenhagen 1 year ago
parent
commit
ee832951e2
  1. 1
      src/.gitignore
  2. 26
      src/Makefile.am
  3. 70
      src/bit_enum_gen.pl
  4. 131
      src/common.h
  5. 2
      src/config.c
  6. 83
      src/driver.h
  7. 2
      src/drv_imap.c
  8. 2
      src/drv_proxy.c
  9. 37
      src/sync.c
  10. 57
      src/sync.h
  11. 43
      src/sync_p.h
  12. 2
      src/sync_state.c

1
src/.gitignore vendored

@ -1,4 +1,3 @@
/*_enum.h
/drv_proxy.inc /drv_proxy.inc
/mbsync /mbsync
/mdconvert /mdconvert

26
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 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 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_SOURCES = mdconvert.c
mdconvert_LDADD = $(DB_LIBS) mdconvert_LDADD = $(DB_LIBS)
if with_mdconvert if with_mdconvert
@ -69,6 +47,6 @@ EXTRA_PROGRAMS = tst_timers
exampledir = $(docdir)/examples exampledir = $(docdir)/examples
example_DATA = mbsyncrc.sample 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

70
src/bit_enum_gen.pl

@ -1,70 +0,0 @@
#!/usr/bin/perl
#
# SPDX-FileCopyrightText: 2022 Oswald Buddenhagen <ossi@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;
}
}
}

131
src/common.h

@ -21,8 +21,6 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "common_enum.h"
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned int uint; typedef unsigned int uint;
@ -43,10 +41,55 @@ typedef unsigned long ulong;
#define shifted_bit(in, from, to) \ #define shifted_bit(in, from, to) \
((int)(((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / from : 1)) & 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) \ #define PFX_BIT_ENUM_STR(pfx, name) \
static_assert( pfx##__NUM_BITS <= sizeof(((type){ 0 }).field) * 8, \ 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" ) stringify(type) "::" stringify(field) " is too small" )
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
@ -100,30 +143,32 @@ enum {
VERBOSE, VERBOSE,
}; };
BIT_ENUM( #define options_enum(fn) \
DEBUG_MAILDIR, fn(DEBUG_MAILDIR) \
DEBUG_NET, fn(DEBUG_NET) \
DEBUG_NET_ALL, fn(DEBUG_NET_ALL) \
DEBUG_SYNC, fn(DEBUG_SYNC) \
DEBUG_MAIN, fn(DEBUG_MAIN) \
DEBUG_DRV, fn(DEBUG_DRV) \
DEBUG_DRV_ALL, fn(DEBUG_DRV_ALL) \
\
DEBUG_CRASH, fn(DEBUG_CRASH) \
\
PROGRESS, fn(PROGRESS) \
\
DRYRUN, fn(DRYRUN) \
\
EXT_EXIT, fn(EXT_EXIT) \
\
ZERODELAY, fn(ZERODELAY) \
KEEPJOURNAL, fn(KEEPJOURNAL) \
FORCEJOURNAL, fn(FORCEJOURNAL) \
FORCEASYNC(2), fn(FORCEASYNC_F) \
FAKEEXPUNGE, fn(FORCEASYNC_N) \
FAKEDUMBSTORE, 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_ANY (DEBUG_MAILDIR | DEBUG_NET | DEBUG_SYNC | DEBUG_MAIN | DEBUG_DRV)
#define DEBUG_ALL (DEBUG_ANY | DEBUG_CRASH) #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 ); void fmt_bits( uint bits, uint num_bits, const char *bit_str, const int *bit_off, char *buf );
#define BIT_FORMATTER_RET(name, pfx) \ #define BIT_FORMATTER_RET(name, list, fn) \
struct name##_str { char str[sizeof(pfx##__STRINGS)]; }; enum { list(fn##_OFF) name##_str_len }; \
struct name##_str { char str[name##_str_len]; };
#define BIT_FORMATTER_PROTO(name, storage) \ #define BIT_FORMATTER_PROTO(name, storage) \
storage struct name##_str ATTR_OPTIMIZE /* force RVO */ \ storage struct name##_str ATTR_OPTIMIZE /* force RVO */ \
fmt_##name( uint bits ) fmt_##name( uint bits )
#define BIT_FORMATTER_IMPL(name, pfx, storage) \ #define BIT_FORMATTER_IMPL(name, list, fn, storage) \
BIT_FORMATTER_PROTO(name, storage) \ BIT_FORMATTER_PROTO(name, storage) \
{ \ { \
static const char strings[] = pfx##__STRINGS; \ static const char strings[] = list(fn); \
static const int offsets[] = { pfx##__OFFSETS }; \ static const int offsets[] = { list(GET_##fn##_OFF) }; \
\ \
struct name##_str buf; \ struct name##_str buf; \
fmt_bits( bits, as(offsets), strings, offsets, buf.str ); \ fmt_bits( bits, as(offsets), strings, offsets, buf.str ); \
return buf; \ return buf; \
} }
#define BIT_FORMATTER_FUNCTION(name, pfx) \ // Note that this one uses enum labels without prefix ...
BIT_FORMATTER_RET(name, pfx) \ #define BIT_FORMATTER_FUNCTION(name, list) \
BIT_FORMATTER_IMPL(name, pfx, static) BIT_FORMATTER_RET(name, list, BIT_ENUM_STR) \
BIT_FORMATTER_IMPL(name, list, BIT_ENUM_STR, static)
#define DECL_BIT_FORMATTER_FUNCTION(name, pfx) \ // ... while these ones use enum labels with prefix - this
BIT_FORMATTER_RET(name, pfx) \ // 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, ); BIT_FORMATTER_PROTO(name, );
#define DEF_BIT_FORMATTER_FUNCTION(name, pfx) \ #define DEF_BIT_FORMATTER_FUNCTION(name, list) \
BIT_FORMATTER_IMPL(name, pfx, ) BIT_FORMATTER_IMPL(name, list, PFX_BIT_ENUM_STR, )
void *nfmalloc( size_t sz ); void *nfmalloc( size_t sz );
void *nfzalloc( size_t sz ); void *nfzalloc( size_t sz );

2
src/config.c

@ -22,7 +22,7 @@ char FieldDelimiter = ';';
char FieldDelimiter = ':'; char FieldDelimiter = ':';
#endif #endif
DEF_BIT_FORMATTER_FUNCTION(ops, OP) DEF_BIT_FORMATTER_FUNCTION(ops, sync_op_enum)
char * char *
expand_strdup( const char *s, const conffile_t *cfile ) expand_strdup( const char *s, const conffile_t *cfile )

83
src/driver.h

@ -9,7 +9,6 @@
#define DRIVER_H #define DRIVER_H
#include "config.h" #include "config.h"
#include "driver_enum.h"
typedef struct driver driver_t; typedef struct driver driver_t;
@ -36,32 +35,32 @@ extern store_conf_t *stores;
/* For message->flags */ /* For message->flags */
// Keep the MESSAGE_FLAGS in sync (grep that)! // Keep the MESSAGE_FLAGS in sync (grep that)!
/* The order is according to alphabetical maildir flag sort */ /* The order is according to alphabetical maildir flag sort */
BIT_ENUM( #define msg_flags_enum(fn) \
F_DRAFT, // Draft fn(F, DRAFT) /* Draft */ \
F_FLAGGED, // Flagged fn(F, FLAGGED) /* Flagged */ \
F_FORWARDED, // Passed fn(F, FORWARDED) /* Passed */ \
F_ANSWERED, // Replied fn(F, ANSWERED) /* Replied */ \
F_SEEN, // Seen fn(F, SEEN) /* Seen */ \
F_DELETED, // Trashed fn(F, DELETED) /* Trashed */
) DEFINE_PFX_BIT_ENUM(msg_flags_enum)
extern const char MsgFlags[F__NUM_BITS]; extern const char MsgFlags[msg_flags_enum_num_bits];
typedef struct { char str[F__NUM_BITS + 1]; } flag_str_t; 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_flags( uchar flags );
flag_str_t ATTR_OPTIMIZE /* force RVO */ fmt_lone_flags( uchar flags ); flag_str_t ATTR_OPTIMIZE /* force RVO */ fmt_lone_flags( uchar flags );
/* For message->status */ /* For message->status */
BIT_ENUM( #define msg_sts_enum(fn) \
M_RECENT, // unsyncable flag; maildir_*() depend on this being bit 0 fn(M, RECENT) /* unsyncable flag; maildir_*() depend on this being bit 0 */ \
M_DEAD, // expunged fn(M, DEAD) /* expunged */ \
M_EXPUNGE, // for driver_t->close_box() fn(M, EXPUNGE) /* for driver_t->close_box() */ \
M_FLAGS, // flags are valid fn(M, FLAGS) /* flags are valid */ \
// The following are only for IMAP FETCH response parsing /* The following are only for IMAP FETCH response parsing */ \
M_DATE, fn(M, DATE) \
M_SIZE, fn(M, SIZE) \
M_BODY, fn(M, BODY) \
M_HEADER, fn(M, HEADER)
) DEFINE_PFX_BIT_ENUM(msg_sts_enum)
#define TUIDL 12 #define TUIDL 12
@ -79,29 +78,29 @@ typedef struct message {
MESSAGE(struct message) MESSAGE(struct message)
} message_t; } message_t;
static_assert_bits(F, message_t, flags); static_assert_bits(msg_flags_enum, message_t, flags);
static_assert_bits(M, message_t, status); static_assert_bits(msg_sts_enum, message_t, status);
// For driver_t->prepare_load_box(), which may amend the passed flags. // 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 // 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 // particular range is required to handle some other flag; note that these
// ranges may overlap. // ranges may overlap.
BIT_ENUM( #define open_flags_enum(fn) \
OPEN_PAIRED, // Paired messages *in* this store. fn(OPEN, PAIRED) /* Paired messages *in* this store. */ \
OPEN_OLD, // Messages that should be already propagated *from* this store. fn(OPEN, OLD) /* Messages that should be already propagated *from* this store. */ \
OPEN_NEW, // Messages (possibly) not yet propagated *from* this store. fn(OPEN, NEW) /* Messages (possibly) not yet propagated *from* this store. */ \
OPEN_FIND, fn(OPEN, FIND) \
OPEN_FLAGS, // Note that fetch_msg() gets the flags regardless. fn(OPEN, FLAGS) /* Note that fetch_msg() gets the flags regardless. */ \
OPEN_OLD_SIZE, fn(OPEN, OLD_SIZE) \
OPEN_NEW_SIZE, fn(OPEN, NEW_SIZE) \
OPEN_PAIRED_IDS, fn(OPEN, PAIRED_IDS) \
OPEN_APPEND, fn(OPEN, APPEND) \
OPEN_SETFLAGS, fn(OPEN, SETFLAGS) \
OPEN_EXPUNGE, fn(OPEN, EXPUNGE) \
// Expunge only deleted messages we know about. Relies on OPEN_{OLD,NEW,FLAGS} /* 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. /* being set externally. The driver may unset it if it can't handle it. */ \
OPEN_UID_EXPUNGE, fn(OPEN, UID_EXPUNGE)
) DEFINE_PFX_BIT_ENUM(open_flags_enum)
#define UIDVAL_BAD ((uint)-1) #define UIDVAL_BAD ((uint)-1)
@ -122,7 +121,7 @@ typedef struct {
uchar flags; uchar flags;
} msg_data_t; } 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 #define DRV_OK 0
/* Message went missing, or mailbox is full, etc. */ /* Message went missing, or mailbox is full, etc. */

2
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) if (i != j)
bl += sprintf( buf + bl, ":%u", excs.data[i] ); 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) if (maxuid == UINT_MAX)
maxuid = ctx->uidnext - 1; maxuid = ctx->uidnext - 1;

2
src/drv_proxy.c

@ -8,7 +8,7 @@
#include "driver.h" #include "driver.h"
BIT_FORMATTER_FUNCTION(opts, OPEN) BIT_FORMATTER_FUNCTION(opts, open_flags_enum)
typedef struct gen_cmd gen_cmd_t; typedef struct gen_cmd gen_cmd_t;

37
src/sync.c

@ -6,7 +6,6 @@
*/ */
#include "sync_p.h" #include "sync_p.h"
#include "sync_c_enum.h"
channel_conf_t global_conf; channel_conf_t global_conf;
channel_conf_t *channels; channel_conf_t *channels;
@ -45,24 +44,24 @@ static int check_cancel( sync_vars_t *svars );
cleanup: close(F) & close(N) cleanup: close(F) & close(N)
*/ */
BIT_ENUM( #define sync_sts_enum(fn) \
ST_PRESENT, fn(ST, PRESENT) \
ST_CONFIRMED, fn(ST, CONFIRMED) \
ST_SELECTED, fn(ST, SELECTED) \
ST_FIND_OLD, fn(ST, FIND_OLD) \
ST_LOADED, fn(ST, LOADED) \
ST_SENT_FLAGS, fn(ST, SENT_FLAGS) \
ST_SENDING_NEW, fn(ST, SENDING_NEW) \
ST_SENT_NEW, fn(ST, SENT_NEW) \
ST_FIND_NEW, fn(ST, FIND_NEW) \
ST_FOUND_NEW, fn(ST, FOUND_NEW) \
ST_SENT_TRASH, fn(ST, SENT_TRASH) \
ST_TRASH_BAD, fn(ST, TRASH_BAD) \
ST_CLOSING, fn(ST, CLOSING) \
ST_CLOSED, fn(ST, CLOSED) \
ST_SENT_CANCEL, fn(ST, SENT_CANCEL) \
ST_CANCELED, fn(ST, CANCELED)
) DEFINE_PFX_BIT_ENUM(sync_sts_enum)
static uchar static uchar
sanitize_flags( uchar tflags, sync_vars_t *svars, int t ) sanitize_flags( uchar tflags, sync_vars_t *svars, int t )

57
src/sync.h

@ -9,44 +9,43 @@
#define SYNC_H #define SYNC_H
#include "driver.h" #include "driver.h"
#include "sync_enum.h"
#define F 0 // far side #define F 0 // far side
#define N 1 // near side #define N 1 // near side
BIT_ENUM( #define sync_op_enum(fn) \
OP_NEW, fn(OP, NEW) \
OP_OLD, fn(OP, OLD) \
OP_UPGRADE, fn(OP, UPGRADE) \
OP_GONE, fn(OP, GONE) \
OP_FLAGS, fn(OP, FLAGS) \
OP_EXPUNGE, fn(OP, EXPUNGE) \
OP_EXPUNGE_SOLO, fn(OP, EXPUNGE_SOLO) \
OP_CREATE, fn(OP, CREATE) \
OP_REMOVE, fn(OP, REMOVE) \
\
XOP_PUSH, fn(XOP, PUSH) \
XOP_PULL, fn(XOP, PULL) \
XOP_HAVE_TYPE, // Aka mode; have at least one of dir and type (see below) 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. /* The following must all have the same bit shift from the corresponding OP_* flags. */ \
XOP_HAVE_EXPUNGE, fn(XOP, HAVE_EXPUNGE) \
XOP_HAVE_EXPUNGE_SOLO, fn(XOP, HAVE_EXPUNGE_SOLO) \
XOP_HAVE_CREATE, fn(XOP, HAVE_CREATE) \
XOP_HAVE_REMOVE, fn(XOP, HAVE_REMOVE) \
// ... until here. /* ... until here. */ \
XOP_TYPE_NOOP, fn(XOP, TYPE_NOOP) \
// ... and here again from scratch. /* ... and here again from scratch. */ \
XOP_EXPUNGE_NOOP, fn(XOP, EXPUNGE_NOOP) \
XOP_EXPUNGE_SOLO_NOOP, fn(XOP, EXPUNGE_SOLO_NOOP) \
XOP_CREATE_NOOP, fn(XOP, CREATE_NOOP) \
XOP_REMOVE_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_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 OP_MASK_TYPE (OP_DFLT_TYPE | OP_OLD) // Asserted in the target side ops
#define XOP_MASK_DIR (XOP_PUSH | XOP_PULL) #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 { typedef struct channel_conf {
struct channel_conf *next; struct channel_conf *next;

43
src/sync_p.h

@ -7,23 +7,28 @@
#define DEBUG_FLAG DEBUG_SYNC #define DEBUG_FLAG DEBUG_SYNC
#include "sync.h" #include "sync.h"
#include "sync_p_enum.h"
#define srec_sts_enum(fn) \
BIT_ENUM( fn(S, DEAD) /* ephemeral: the entry was killed and should be ignored */ \
S_DEAD, // ephemeral: the entry was killed and should be ignored fn(S, EXPIRE) /* the entry is being expired (expire-side message removal scheduled) */ \
S_EXPIRE, // the entry is being expired (expire-side message removal scheduled) fn(S, EXPIRED) /* the entry is expired (expire-side message removal confirmed) */ \
S_EXPIRED, // the entry is expired (expire-side message removal confirmed) fn(S, NEXPIRE) /* temporary: new expiration state */ \
S_NEXPIRE, // temporary: new expiration state fn(S, PENDING) /* the entry is new and awaits propagation (possibly a retry) */ \
S_PENDING, // the entry is new and awaits propagation (possibly a retry) fn(S, DUMMY_F) /* f/n message is only a placeholder */ \
S_DUMMY(2), // f/n message is only a placeholder fn(S, DUMMY_N) \
S_SKIPPED, // pre-1.4 legacy: the entry was not propagated (message is too big) fn(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 fn(S, GONE_F) /* ephemeral: f/n message has been expunged */ \
S_DEL(2), // ephemeral: f/n message would be subject to non-selective expunge fn(S, GONE_N) \
S_DELETE, // ephemeral: flags propagation is a deletion fn(S, DEL_F) /* ephemeral: f/n message would be subject to non-selective expunge */ \
S_UPGRADE, // ephemeral: upgrading placeholder, do not apply MaxSize fn(S, DEL_N) \
S_PURGE, // ephemeral: placeholder is being nuked fn(S, DELETE) /* ephemeral: flags propagation is a deletion */ \
S_PURGED, // ephemeral: placeholder was nuked 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. // 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) #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]; char tuid[TUIDL];
} sync_rec_t; } sync_rec_t;
static_assert_bits(F, sync_rec_t, flags); static_assert_bits(msg_flags_enum, sync_rec_t, flags);
static_assert_bits(S, sync_rec_t, status); static_assert_bits(srec_sts_enum, sync_rec_t, status);
typedef struct { typedef struct {
int t[2]; int t[2];

2
src/sync_state.c

@ -17,7 +17,7 @@
const char *str_fn[] = { "far side", "near side" }, *str_hl[] = { "push", "pull" }; 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 * static char *
clean_strdup( const char *s ) clean_strdup( const char *s )

Loading…
Cancel
Save