macros.h revision 4ab8814199f67c28b30f6aeef77d045fc856dc30
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch#ifndef MACROS_H
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define MACROS_H
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* several useful macros, mostly from glib.h */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifndef NULL
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define NULL ((void *)0)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifndef FALSE
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define FALSE (!1)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifndef TRUE
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define TRUE (!FALSE)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define N_ELEMENTS(arr) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch (sizeof(arr) / sizeof((arr)[0]))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define MEM_ALIGN(size) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch (((size) + MEM_ALIGN_SIZE-1) & ~((size_t) MEM_ALIGN_SIZE-1))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define PTR_OFFSET(ptr, offset) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((void *) (((unsigned char *) (ptr)) + (offset)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define CONST_PTR_OFFSET(ptr, offset) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((const void *) (((const unsigned char *) (ptr)) + (offset)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Don't use simply MIN/MAX, as they're often defined elsewhere in include
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch files that are included after this file generating tons of warnings. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define I_MIN(a, b) (((a) < (b)) ? (a) : (b))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define I_MAX(a, b) (((a) > (b)) ? (a) : (b))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* make it easier to cast from/to pointers. assumes that
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch sizeof(size_t) == sizeof(void *) and they're both the largest datatypes
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch that are allowed to be used. so, long long isn't safe with these. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define POINTER_CAST(i) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((void *) ((char *) NULL + (i)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define POINTER_CAST_TO(p, type) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((type) ((const char *) (p) - (const char *) NULL))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Define VA_COPY() to do the right thing for copying va_list variables.
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch config.h may have already defined VA_COPY as va_copy or __va_copy. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifndef VA_COPY
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# if defined (__GNUC__) && defined (__PPC__) && \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch (defined (_CALL_SYSV) || defined (_WIN32))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# elif defined (VA_COPY_AS_ARRAY)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# else /* va_list is a pointer */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define VA_COPY(ap1, ap2) ((ap1) = (ap2))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# endif /* va_list is a pointer */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Provide convenience macros for handling structure
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch * fields through their offsets.
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define STRUCT_MEMBER_P(struct_p, struct_offset) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((void *) ((char *) (struct_p) + (long) (struct_offset)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define CONST_STRUCT_MEMBER_P(struct_p, struct_offset) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch ((const void *) ((const char *) (struct_p) + (long) (struct_offset)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Provide simple macro statement wrappers (adapted from Perl):
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch STMT_START { statements; } STMT_END;
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch can be used as a single statement, as in
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch if (x) STMT_START { ... } STMT_END; else ...
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch For gcc we will wrap the statements within `({' and `})' braces.
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch For SunOS they will be wrapped within `if (1)' and `else (void) 0',
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch and otherwise within `do' and `while (0)'. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if !(defined (STMT_START) && defined (STMT_END))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# if defined (__GNUC__) && !defined (__cplusplus) && \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch !defined (__STRICT_ANSI__) && !defined (PEDANTIC)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_START (void)(
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_END )
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# if (defined (sun) || defined (__sun__))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_START if (1)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_END else (void)0
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_START do
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define STMT_END while (0)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Provide macros to feature the GCC function attribute. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTRS_DEFINED
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_FORMAT(format_idx, arg_idx) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __attribute__((format (printf, format_idx, arg_idx)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_FORMAT_ARG(arg_idx) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __attribute__((format_arg (arg_idx)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_SCANF(format_idx, arg_idx) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __attribute__((format (scanf, format_idx, arg_idx)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_STRFTIME(format_idx) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __attribute__((format (strftime, format_idx, 0)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_UNUSED __attribute__((unused))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NORETURN __attribute__((noreturn))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_CONST __attribute__((const))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_PURE __attribute__((pure))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_FORMAT(format_idx, arg_idx)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_FORMAT_ARG(arg_idx)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_SCANF(format_idx, arg_idx)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_STRFTIME(format_idx)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_UNUSED
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NORETURN
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_CONST
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_PURE
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifdef HAVE_ATTR_NULL
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NULL(...) __attribute__((null(__VA_ARGS__)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NULL(...)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifdef HAVE_ATTR_NOWARN_UNUSED_RESULT
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NOWARN_UNUSED_RESULT __attribute__((nowarn_unused_result))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_NOWARN_UNUSED_RESULT
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 2
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_MALLOC __attribute__((malloc))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_MALLOC
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 3
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* GCC 4.0 and later */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_SENTINEL __attribute__((sentinel))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_WARN_UNUSED_RESULT
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_SENTINEL
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* GCC 4.3 and later */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_HOT __attribute__((hot))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_COLD __attribute__((cold))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_HOT
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_COLD
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* GCC 4.9 and later */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_RETURNS_NONNULL __attribute__((returns_nonnull))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define ATTR_RETURNS_NONNULL
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Macros to provide type safety for callback functions' context parameters */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if ((__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) && defined(HAVE_TYPEOF))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define CALLBACK_TYPECHECK(callback, type) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch (COMPILE_ERROR_IF_TRUE(!__builtin_types_compatible_p( \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch typeof(&callback), type)) ? 1 : 0)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define CALLBACK_TYPECHECK(callback, type) 0
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)) && !defined(__cplusplus)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define COMPILE_ERROR_IF_TRUE(condition) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch (sizeof(char[1 - 2 * !!(condition)]) - 1)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define COMPILE_ERROR_IF_TRUE(condition) 0
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)) && !defined(__cplusplus) && defined(HAVE_TYPEOF)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch COMPILE_ERROR_IF_TRUE( \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch !__builtin_types_compatible_p(typeof(_a), typeof(_b)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define COMPILE_ERROR_IF_TYPES2_NOT_COMPATIBLE(_a1, _a2, _b) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch COMPILE_ERROR_IF_TRUE( \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch !__builtin_types_compatible_p(typeof(_a1), typeof(_b)) && \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch !__builtin_types_compatible_p(typeof(_a2), typeof(_b)))
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) 0
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define COMPILE_ERROR_IF_TYPES2_NOT_COMPATIBLE(_a1, _a2, _b) 0
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#if __GNUC__ > 2
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define unlikely(expr) (__builtin_expect((expr) ? 1 : 0, 0) != 0)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define likely(expr) (__builtin_expect((expr) ? 1 : 0, 1) != 0)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define unlikely(expr) expr
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define likely(expr) expr
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch/* Provide macros for error handling. */
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#ifdef DISABLE_ASSERTS
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch# define i_assert(expr)
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#else
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define i_assert(expr) STMT_START{ \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch if (unlikely(!(expr))) \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch i_panic("file %s: line %d (%s): assertion failed: (%s)", \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __FILE__, \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __LINE__, \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch __func__, \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch #expr); }STMT_END
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#endif
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch#define i_close_fd(fd) STMT_START { \
30116399ebac74cf4ea0daefb65c9fba742e0773Stephan Bosch i_assert(*fd != -1); \
if (unlikely(close_keep_errno(fd) < 0)) \
i_error("close(%d[%s:%d]) failed: %m", \
*(fd), __FILE__, __LINE__); \
} STMT_END
#define i_unreached() \
i_panic("file %s: line %d: unreached", __FILE__, __LINE__)
/* Convenience macros to test the versions of dovecot. */
#if defined DOVECOT_VERSION_MAJOR && defined DOVECOT_VERSION_MINOR
# define DOVECOT_PREREQ(maj, min) \
((DOVECOT_VERSION_MAJOR << 16) + DOVECOT_VERSION_MINOR >= ((maj) << 16) + (min))
#else
# define DOVECOT_PREREQ(maj, min) 0
#endif
#ifdef __cplusplus
# undef STATIC_ARRAY
# define STATIC_ARRAY
#endif
#endif