macros.h revision c3c07d6527ad28c8546cbbf84c257d178e23c184
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen#ifndef MACROS_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MACROS_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen/* several useful macros, mostly from glib.h */
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifndef NULL
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen# define NULL ((void *)0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#endif
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifndef FALSE
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen# define FALSE (0)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifndef TRUE
66ae183b6e895216037bd921367670f4b0665911Timo Sirainen# define TRUE (!FALSE)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#endif
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define N_ELEMENTS(arr) \
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen (sizeof(arr) / sizeof((arr)[0]))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MEM_ALIGN(size) \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (((size) + MEM_ALIGN_SIZE-1) & ~((unsigned int) MEM_ALIGN_SIZE-1))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#define PTR_OFFSET(ptr, offset) \
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen ((void *) (((unsigned char *) (ptr)) + (offset)))
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen#define CONST_PTR_OFFSET(ptr, offset) \
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen ((const void *) (((const unsigned char *) (ptr)) + (offset)))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Don't use simply MIN/MAX, as they're often defined elsewhere in include
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen files that are included after this file generating tons of warnings. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define I_MIN(a, b) (((a) < (b)) ? (a) : (b))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define I_MAX(a, b) (((a) > (b)) ? (a) : (b))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* make it easier to cast from/to pointers. assumes that
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sizeof(size_t) == sizeof(void *) and they're both the largest datatypes
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen that are allowed to be used. so, long long isn't safe with these. */
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen#define POINTER_CAST(i) \
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen ((void *) ((char *) NULL + (i)))
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen#define POINTER_CAST_TO(p, type) \
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen ((type) ((const char *) (p) - (const char *) NULL))
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen/* Define VA_COPY() to do the right thing for copying va_list variables.
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen config.h may have already defined VA_COPY as va_copy or __va_copy. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifndef VA_COPY
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# if defined (__GNUC__) && defined (__PPC__) && \
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen (defined (_CALL_SYSV) || defined (_WIN32))
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen# define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
5aeb15e5817fbd4b1d8de540aa7673e3819a8030Timo Sirainen# elif defined (VA_COPY_AS_ARRAY)
5aeb15e5817fbd4b1d8de540aa7673e3819a8030Timo Sirainen# define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen# else /* va_list is a pointer */
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen# define VA_COPY(ap1, ap2) ((ap1) = (ap2))
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen# endif /* va_list is a pointer */
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen#endif
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen/* Provide convenience macros for handling structure
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen * fields through their offsets.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define STRUCT_MEMBER_P(struct_p, struct_offset) \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ((void *) ((char *) (struct_p) + (long) (struct_offset)))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen#define CONST_STRUCT_MEMBER_P(struct_p, struct_offset) \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ((const void *) ((const char *) (struct_p) + (long) (struct_offset)))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen/* Provide simple macro statement wrappers (adapted from Perl):
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen STMT_START { statements; } STMT_END;
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen can be used as a single statement, as in
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (x) STMT_START { ... } STMT_END; else ...
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen For gcc we will wrap the statements within `({' and `})' braces.
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen For SunOS they will be wrapped within `if (1)' and `else (void) 0',
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen and otherwise within `do' and `while (0)'. */
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen#if !(defined (STMT_START) && defined (STMT_END))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen# if defined (__GNUC__) && !defined (__cplusplus) && \
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen !defined (__STRICT_ANSI__) && !defined (PEDANTIC)
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen# define STMT_START (void)(
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen# define STMT_END )
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen# else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# if (defined (sun) || defined (__sun__))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# define STMT_START if (1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# define STMT_END else (void)0
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# define STMT_START do
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# define STMT_END while (0)
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen# endif
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen# endif
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen#endif
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen/* Provide macros to feature the GCC function attribute. */
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen# define ATTRS_DEFINED
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen# define ATTR_FORMAT(format_idx, arg_idx) \
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen __attribute__((format (printf, format_idx, arg_idx)))
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen# define ATTR_FORMAT_ARG(arg_idx) \
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen __attribute__((format_arg (arg_idx)))
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen# define ATTR_SCANF(format_idx, arg_idx) \
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen __attribute__((format (scanf, format_idx, arg_idx)))
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen# define ATTR_STRFTIME(format_idx) \
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen __attribute__((format (strftime, format_idx, 0)))
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen# define ATTR_UNUSED __attribute__((unused))
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen# define ATTR_NORETURN __attribute__((noreturn))
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen# define ATTR_CONST __attribute__((const))
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen# define ATTR_PURE __attribute__((pure))
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#else
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen# define ATTR_FORMAT(format_idx, arg_idx)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen# define ATTR_FORMAT_ARG(arg_idx)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_SCANF(format_idx, arg_idx)
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen# define ATTR_STRFTIME(format_idx)
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen# define ATTR_UNUSED
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen# define ATTR_NORETURN
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen# define ATTR_CONST
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainen# define ATTR_PURE
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen#endif
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainen#if __GNUC__ > 2
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen# define ATTR_MALLOC __attribute__((malloc))
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen#else
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_MALLOC
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#endif
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen#if __GNUC__ > 3
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen/* GCC 4.0 and later */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen# define ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_SENTINEL __attribute__((sentinel))
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen#else
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen# define ATTR_WARN_UNUSED_RESULT
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen# define ATTR_SENTINEL
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen#endif
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen/* GCC 4.3 and later */
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_HOT __attribute__((hot))
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_COLD __attribute__((cold))
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#else
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_HOT
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define ATTR_COLD
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#endif
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen/* Macros to provide type safety for callback functions' context parameters */
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#ifdef __GNUC__
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define CONTEXT_TYPE_SAFETY
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#endif
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen#ifdef CONTEXT_TYPE_SAFETY
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define CONTEXT_CALLBACK(name, callback_type, callback, context, ...) \
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen ({(void)(1 ? 0 : callback(context)); \
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen name(__VA_ARGS__, (callback_type *)callback, context); })
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen# define CONTEXT_CALLBACK2(name, callback_type, callback, arg1_type, context, ...) \
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen ({(void)(1 ? 0 : callback((arg1_type)0, context)); \
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen name(__VA_ARGS__, (callback_type *)callback, context); })
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen#else
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen# define CONTEXT_CALLBACK(name, callback_type, callback, context, ...) \
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen name(__VA_ARGS__, (callback_type *)callback, context)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen# define CONTEXT_CALLBACK2(name, callback_type, callback, arg1_type, context, ...) \
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen name(__VA_ARGS__, (callback_type *)callback, context)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen#endif
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define HAVE_TYPEOF
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen# define COMPILE_ERROR_IF_TRUE(condition) \
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen (sizeof(char[1 - 2 * !!(condition)]) - 1)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) \
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen COMPILE_ERROR_IF_TRUE( \
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen !__builtin_types_compatible_p(typeof(_a), typeof(_b)))
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen#else
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define COMPILE_ERROR_IF_TRUE(condition) 0
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(_a, _b) 0
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen#endif
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen#if __GNUC__ > 2
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen# define unlikely(expr) __builtin_expect(!!(expr), 0)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define likely(expr) __builtin_expect(!!(expr), 1)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen#else
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen# define unlikely(expr) expr
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen# define likely(expr) expr
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen#endif
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen/* Provide macros for error handling. */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#ifdef DISABLE_ASSERTS
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen# define i_assert(expr)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen#elif defined (__GNUC__) && !defined (__STRICT_ANSI__)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen#define i_assert(expr) STMT_START{ \
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (unlikely(!(expr))) \
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen i_panic("file %s: line %d (%s): assertion failed: (%s)", \
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen __FILE__, \
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen __LINE__, \
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen __FUNCTION__, \
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen #expr); }STMT_END
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#else /* !__GNUC__ */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen#define i_assert(expr) STMT_START{ \
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (unlikely(!(expr))) \
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen i_panic("file %s: line %d: assertion failed: (%s)", \
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen __FILE__, \
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen __LINE__, \
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen #expr); }STMT_END
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen#endif
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen#define i_unreached() \
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen i_panic("file %s: line %d: unreached", __FILE__, __LINE__)
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen#endif
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen