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.
This commit is contained in:
parent
05122b678d
commit
6a78e2c5f6
1
src/.gitignore
vendored
1
src/.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
/*_enum.h
|
||||||
/drv_proxy.inc
|
/drv_proxy.inc
|
||||||
/mbsync
|
/mbsync
|
||||||
/mdconvert
|
/mdconvert
|
||||||
|
|
|
@ -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
|
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
|
||||||
|
@ -36,6 +58,6 @@ EXTRA_PROGRAMS = tst_timers
|
||||||
exampledir = $(docdir)/examples
|
exampledir = $(docdir)/examples
|
||||||
example_DATA = mbsyncrc.sample
|
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
|
||||||
|
|
55
src/bit_enum_gen.pl
Executable file
55
src/bit_enum_gen.pl
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/common.h
33
src/common.h
|
@ -21,6 +21,8 @@
|
||||||
#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;
|
||||||
|
@ -41,6 +43,8 @@ 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(...)
|
||||||
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
||||||
# define ATTR_UNUSED __attribute__((unused))
|
# define ATTR_UNUSED __attribute__((unused))
|
||||||
# define ATTR_NORETURN __attribute__((noreturn))
|
# define ATTR_NORETURN __attribute__((noreturn))
|
||||||
|
@ -90,18 +94,23 @@ enum {
|
||||||
VERBOSE,
|
VERBOSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEBUG_CRASH 0x01
|
BIT_ENUM(
|
||||||
#define DEBUG_MAILDIR 0x02
|
DEBUG_MAILDIR,
|
||||||
#define DEBUG_NET 0x04
|
DEBUG_NET,
|
||||||
#define DEBUG_NET_ALL 0x08
|
DEBUG_NET_ALL,
|
||||||
#define DEBUG_SYNC 0x10
|
DEBUG_SYNC,
|
||||||
#define DEBUG_MAIN 0x20
|
DEBUG_MAIN,
|
||||||
#define DEBUG_DRV 0x40
|
DEBUG_DRV,
|
||||||
#define DEBUG_DRV_ALL 0x80
|
DEBUG_DRV_ALL,
|
||||||
#define PROGRESS 0x400
|
|
||||||
#define KEEPJOURNAL 0x1000
|
DEBUG_CRASH,
|
||||||
#define ZERODELAY 0x2000
|
|
||||||
#define FORCEASYNC 0x4000
|
PROGRESS,
|
||||||
|
|
||||||
|
ZERODELAY,
|
||||||
|
KEEPJOURNAL,
|
||||||
|
FORCEASYNC,
|
||||||
|
)
|
||||||
|
|
||||||
#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)
|
||||||
|
|
56
src/driver.h
56
src/driver.h
|
@ -9,6 +9,7 @@
|
||||||
#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;
|
||||||
|
|
||||||
|
@ -33,26 +34,29 @@ typedef struct store_conf {
|
||||||
/* 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 */
|
||||||
#define F_DRAFT (1<<0) /* Draft */
|
BIT_ENUM(
|
||||||
#define F_FLAGGED (1<<1) /* Flagged */
|
F_DRAFT, // Draft
|
||||||
#define F_FORWARDED (1<<2) /* Passed */
|
F_FLAGGED, // Flagged
|
||||||
#define F_ANSWERED (1<<3) /* Replied */
|
F_FORWARDED, // Passed
|
||||||
#define F_SEEN (1<<4) /* Seen */
|
F_ANSWERED, // Replied
|
||||||
#define F_DELETED (1<<5) /* Trashed */
|
F_SEEN, // Seen
|
||||||
#define NUM_FLAGS 6
|
F_DELETED, // Trashed
|
||||||
|
)
|
||||||
|
|
||||||
extern const char MsgFlags[NUM_FLAGS];
|
extern const char MsgFlags[F__NUM_BITS];
|
||||||
void make_flags( uchar flags, char *buf );
|
void make_flags( uchar flags, char *buf );
|
||||||
|
|
||||||
/* For message->status */
|
/* For message->status */
|
||||||
#define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
|
BIT_ENUM(
|
||||||
#define M_DEAD (1<<1) /* expunged */
|
M_RECENT, // unsyncable flag; maildir_*() depend on this being bit 0
|
||||||
#define M_FLAGS (1<<2) /* flags fetched */
|
M_DEAD, // expunged
|
||||||
// The following are only for IMAP FETCH response parsing
|
M_FLAGS, // flags are valid
|
||||||
#define M_DATE (1<<3)
|
// The following are only for IMAP FETCH response parsing
|
||||||
#define M_SIZE (1<<4)
|
M_DATE,
|
||||||
#define M_BODY (1<<5)
|
M_SIZE,
|
||||||
#define M_HEADER (1<<6)
|
M_BODY,
|
||||||
|
M_HEADER,
|
||||||
|
)
|
||||||
|
|
||||||
#define TUIDL 12
|
#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
|
// 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
|
// particular range is required to handle some other flag; note that these
|
||||||
// ranges may overlap.
|
// ranges may overlap.
|
||||||
#define OPEN_OLD (1<<0) // Paired messages *in* this store.
|
BIT_ENUM(
|
||||||
#define OPEN_NEW (1<<1) // Messages (possibly) not yet propagated *from* this store.
|
OPEN_OLD, // Paired messages *in* this store.
|
||||||
#define OPEN_FLAGS (1<<2) // Note that fetch_msg() gets the flags regardless.
|
OPEN_NEW, // Messages (possibly) not yet propagated *from* this store.
|
||||||
#define OPEN_NEW_SIZE (1<<4)
|
OPEN_FIND,
|
||||||
#define OPEN_EXPUNGE (1<<5)
|
OPEN_FLAGS, // Note that fetch_msg() gets the flags regardless.
|
||||||
#define OPEN_SETFLAGS (1<<6)
|
OPEN_NEW_SIZE,
|
||||||
#define OPEN_APPEND (1<<7)
|
OPEN_OLD_IDS,
|
||||||
#define OPEN_FIND (1<<8)
|
OPEN_APPEND,
|
||||||
#define OPEN_OLD_IDS (1<<9)
|
OPEN_SETFLAGS,
|
||||||
|
OPEN_EXPUNGE,
|
||||||
|
)
|
||||||
|
|
||||||
#define UIDVAL_BAD ((uint)-1)
|
#define UIDVAL_BAD ((uint)-1)
|
||||||
|
|
||||||
|
|
|
@ -1565,7 +1565,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||||
const char *box;
|
const char *box;
|
||||||
int ret, fd, bl;
|
int ret, fd, bl;
|
||||||
uint uid;
|
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 );
|
bl = nfsnprintf( base, sizeof(base), "%lld.%d_%d.%s", (long long)time( NULL ), Pid, ++MaildirCount, Hostname );
|
||||||
if (!to_trash) {
|
if (!to_trash) {
|
||||||
|
|
36
src/sync.c
36
src/sync.c
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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;
|
||||||
|
@ -43,23 +44,24 @@ static int check_cancel( sync_vars_t *svars );
|
||||||
cleanup: close(F) & close(N)
|
cleanup: close(F) & close(N)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ST_LOADED (1<<0)
|
BIT_ENUM(
|
||||||
#define ST_FIND_OLD (1<<1)
|
ST_PRESENT,
|
||||||
#define ST_SENT_NEW (1<<2)
|
ST_CONFIRMED,
|
||||||
#define ST_FIND_NEW (1<<3)
|
ST_SELECTED,
|
||||||
#define ST_FOUND_NEW (1<<4)
|
ST_FIND_OLD,
|
||||||
#define ST_SENT_FLAGS (1<<5)
|
ST_LOADED,
|
||||||
#define ST_SENT_TRASH (1<<6)
|
ST_SENT_FLAGS,
|
||||||
#define ST_CLOSED (1<<7)
|
ST_SENDING_NEW,
|
||||||
#define ST_SENT_CANCEL (1<<8)
|
ST_SENT_NEW,
|
||||||
#define ST_CANCELED (1<<9)
|
ST_FIND_NEW,
|
||||||
#define ST_SELECTED (1<<10)
|
ST_FOUND_NEW,
|
||||||
#define ST_DID_EXPUNGE (1<<11)
|
ST_SENT_TRASH,
|
||||||
#define ST_CLOSING (1<<12)
|
ST_CLOSING,
|
||||||
#define ST_CONFIRMED (1<<13)
|
ST_CLOSED,
|
||||||
#define ST_PRESENT (1<<14)
|
ST_DID_EXPUNGE,
|
||||||
#define ST_SENDING_NEW (1<<15)
|
ST_SENT_CANCEL,
|
||||||
|
ST_CANCELED,
|
||||||
|
)
|
||||||
|
|
||||||
static uchar
|
static uchar
|
||||||
sanitize_flags( uchar tflags, sync_vars_t *svars, int t )
|
sanitize_flags( uchar tflags, sync_vars_t *svars, int t )
|
||||||
|
|
37
src/sync.h
37
src/sync.h
|
@ -9,26 +9,31 @@
|
||||||
#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
|
||||||
|
|
||||||
#define OP_NEW (1<<0)
|
BIT_ENUM(
|
||||||
#define OP_RENEW (1<<1)
|
OP_NEW,
|
||||||
#define OP_DELETE (1<<2)
|
OP_RENEW,
|
||||||
#define OP_FLAGS (1<<3)
|
OP_DELETE,
|
||||||
#define OP_MASK_TYPE (OP_NEW|OP_RENEW|OP_DELETE|OP_FLAGS) /* asserted in the target ops */
|
OP_FLAGS,
|
||||||
#define OP_EXPUNGE (1<<4)
|
OP_EXPUNGE,
|
||||||
#define OP_CREATE (1<<5)
|
OP_CREATE,
|
||||||
#define OP_REMOVE (1<<6)
|
OP_REMOVE,
|
||||||
#define XOP_PUSH (1<<8)
|
|
||||||
#define XOP_PULL (1<<9)
|
XOP_PUSH,
|
||||||
#define XOP_MASK_DIR (XOP_PUSH|XOP_PULL)
|
XOP_PULL,
|
||||||
#define XOP_HAVE_TYPE (1<<10) // Aka mode; at least one of dir and type
|
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.
|
||||||
#define XOP_HAVE_EXPUNGE (1<<11)
|
XOP_HAVE_EXPUNGE,
|
||||||
#define XOP_HAVE_CREATE (1<<12)
|
XOP_HAVE_CREATE,
|
||||||
#define XOP_HAVE_REMOVE (1<<13)
|
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 {
|
typedef struct channel_conf {
|
||||||
struct channel_conf *next;
|
struct channel_conf *next;
|
||||||
|
|
27
src/sync_p.h
27
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"
|
||||||
|
|
||||||
// This is the (mostly) persistent status of the sync record.
|
// This is the (mostly) persistent status of the sync record.
|
||||||
// Most of these bits are actually mutually exclusive. It is a
|
// Most of these bits are actually mutually exclusive. It is a
|
||||||
// bitfield to allow for easy testing for multiple states.
|
// bitfield to allow for easy testing for multiple states.
|
||||||
#define S_EXPIRE (1<<0) // the entry is being expired (near side message removal scheduled)
|
BIT_ENUM(
|
||||||
#define S_EXPIRED (1<<1) // the entry is expired (near side message removal confirmed)
|
S_DEAD, // ephemeral: the entry was killed and should be ignored
|
||||||
#define S_PENDING (1<<2) // the entry is new and awaits propagation (possibly a retry)
|
S_EXPIRE, // the entry is being expired (near side message removal scheduled)
|
||||||
#define S_DUMMY(fn) (1<<(3+(fn))) // f/n message is only a placeholder
|
S_EXPIRED, // the entry is expired (near side message removal confirmed)
|
||||||
#define S_SKIPPED (1<<5) // pre-1.4 legacy: the entry was not propagated (message is too big)
|
S_PENDING, // the entry is new and awaits propagation (possibly a retry)
|
||||||
#define S_DEAD (1<<7) // ephemeral: the entry was killed and should be ignored
|
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.
|
// Ephemeral working set.
|
||||||
#define W_NEXPIRE (1<<0) // temporary: new expiration state
|
BIT_ENUM(
|
||||||
#define W_DELETE (1<<1) // ephemeral: flags propagation is a deletion
|
W_NEXPIRE, // temporary: new expiration state
|
||||||
#define W_DEL(fn) (1<<(2+(fn))) // ephemeral: f/n message would be subject to expunge
|
W_DELETE, // ephemeral: flags propagation is a deletion
|
||||||
#define W_UPGRADE (1<<4) // ephemeral: upgrading placeholder, do not apply MaxSize
|
W_DEL(2), // ephemeral: f/n message would be subject to expunge
|
||||||
#define W_PURGE (1<<5) // ephemeral: placeholder is being nuked
|
W_UPGRADE, // ephemeral: upgrading placeholder, do not apply MaxSize
|
||||||
|
W_PURGE, // ephemeral: placeholder is being nuked
|
||||||
|
)
|
||||||
|
|
||||||
typedef struct sync_rec {
|
typedef struct sync_rec {
|
||||||
struct sync_rec *next;
|
struct sync_rec *next;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.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" };
|
const char *str_fn[] = { "far side", "near side" }, *str_hl[] = { "push", "pull" };
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user