Annotation of embedaddon/bird2/lib/macro.h, revision 1.1

1.1     ! misho       1: /* 
        !             2:  *     BIRD Macro Tricks
        !             3:  *
        !             4:  *     (c) 2018 Jan Maria Matejka <mq@jmq.cz>
        !             5:  *
        !             6:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             7:  *
        !             8:  *     Contains useful but dirty macro tricks:
        !             9:  *             MACRO_CONCAT(a, b)      -> concatenates a##b
        !            10:  *             MACRO_BOOL(x)           -> convert 0 to 0, anything else to 1
        !            11:  *             MACRO_IFELSE(b)(true-branch)(false-branch)
        !            12:  *                                     -> b shall be 0 or 1; expands to the appropriate branch
        !            13:  *             MACRO_ISEMPTY(...)      -> 1 for empty argument list, 0 otherwise
        !            14:  *             MACRO_FOREACH(func, ...)
        !            15:  *                                     -> calling FOREACH(func, a, b, c, d) expands to
        !            16:  *                                             func(a) func(b) func(c) func(d)
        !            17:  *             MACRO_RPACK(func, terminator, ...)
        !            18:  *                                     -> packs the list into recursive calls:
        !            19:  *                                             func(func(func(func(terminator, a), b), c), d)
        !            20:  */
        !            21: 
        !            22: #ifndef _BIRD_MACRO_H_
        !            23: #define _BIRD_MACRO_H_
        !            24: 
        !            25: /* What to do with args */
        !            26: #define MACRO_DROP(...)
        !            27: #define MACRO_UNPAREN(...) __VA_ARGS__
        !            28: #define MACRO_SEP(a, b, sep)  a sep b
        !            29: 
        !            30: /* Aliases for some special chars */
        !            31: #define MACRO_COMMA ,
        !            32: #define MACRO_LPAREN (
        !            33: #define MACRO_RPAREN )
        !            34: #define MACRO_LPAREN_() (
        !            35: #define MACRO_RPAREN_() )
        !            36: 
        !            37: /* Multiple expansion trick */
        !            38: #define MACRO_EXPAND0(...) __VA_ARGS__
        !            39: #define MACRO_EXPAND1(...) MACRO_EXPAND0(MACRO_EXPAND0(__VA_ARGS__))
        !            40: #define MACRO_EXPAND2(...) MACRO_EXPAND1(MACRO_EXPAND1(__VA_ARGS__))
        !            41: #define MACRO_EXPAND3(...) MACRO_EXPAND2(MACRO_EXPAND2(__VA_ARGS__))
        !            42: #define MACRO_EXPAND(...) MACRO_EXPAND3(MACRO_EXPAND3(__VA_ARGS__))
        !            43: 
        !            44: /* Deferring expansion in the expansion trick */
        !            45: #define MACRO_EMPTY()
        !            46: #define MACRO_DEFER(t) t MACRO_EMPTY()
        !            47: #define MACRO_DEFER2(t) t MACRO_EMPTY MACRO_EMPTY()()
        !            48: #define MACRO_DEFER3(t) t MACRO_EMPTY MACRO_EMPTY MACRO_EMPTY()()()
        !            49: 
        !            50: /* Token concatenation */
        !            51: #define MACRO_CONCAT(prefix, ...) prefix##__VA_ARGS__
        !            52: #define MACRO_CONCAT_AFTER(...) MACRO_CONCAT(__VA_ARGS__)
        !            53: 
        !            54: /* Get first or second argument only */
        !            55: #define MACRO_FIRST(a, ...) a
        !            56: #define MACRO_SECOND(a, b, ...) b
        !            57: #define MACRO_SECOND_OR_ZERO(...) MACRO_SECOND(__VA_ARGS__, 0,)
        !            58: 
        !            59: /* Macro Boolean auxiliary macros */
        !            60: #define MACRO_BOOL_CHECK_0 ~, 1
        !            61: #define MACRO_BOOL_NEG(x) MACRO_SECOND_OR_ZERO(MACRO_CONCAT(MACRO_BOOL_CHECK_, x))
        !            62: 
        !            63: #define MACRO_BOOL_NOT_0  1
        !            64: #define MACRO_BOOL_NOT_1  0
        !            65: 
        !            66: /* Macro Boolean negation */
        !            67: #define MACRO_NOT(x) MACRO_CONCAT(MACRO_BOOL_NOT_, x)
        !            68: 
        !            69: /* Convert anything to bool (anything -> 1, 0 -> 0) */
        !            70: #define MACRO_BOOL(x) MACRO_NOT(MACRO_BOOL_NEG(x))
        !            71: 
        !            72: /*
        !            73:  * Macro If/Else condition
        !            74:  * Usage: MACRO_IFELSE(condition)(true-branch)(false-branch)
        !            75:  * Expands to true-branch if condition is true, otherwise to false-branch.
        !            76:  */
        !            77: #define MACRO_IFELSE(b) MACRO_CONCAT(MACRO_IFELSE_, b)
        !            78: #define MACRO_IFELSE_0(...) MACRO_UNPAREN
        !            79: #define MACRO_IFELSE_1(...) __VA_ARGS__ MACRO_DROP
        !            80: 
        !            81: /* Auxiliary macros for MACRO_FOREACH */
        !            82: #define MACRO_ISLAST(...) MACRO_BOOL_NEG(MACRO_FIRST(MACRO_ISLAST_CHECK __VA_ARGS__)())
        !            83: #define MACRO_ISLAST_CHECK() 0
        !            84: 
        !            85: #define MACRO_FOREACH_EXPAND(call, a, ...) MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))(call(a))(call(a) MACRO_DEFER2(MACRO_FOREACH_PAREN)()(call, __VA_ARGS__))
        !            86: #define MACRO_FOREACH_PAREN() MACRO_FOREACH_EXPAND
        !            87: 
        !            88: #define MACRO_RPACK_EXPAND(call, terminator, a, ...) MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))(call(terminator, a))(call(MACRO_DEFER2(MACRO_RPACK_PAREN)()(call, terminator, __VA_ARGS__), a))
        !            89: #define MACRO_RPACK_PAREN() MACRO_RPACK_EXPAND
        !            90: /*
        !            91:  * Call the first argument for each following:
        !            92:  * MACRO_FOREACH(func, a, b, c, d) expands to func(a) func(b) func(c) func(d).
        !            93:  * It supports also macros as func.
        !            94:  */
        !            95: #define MACRO_FOREACH(call, ...) MACRO_EXPAND(MACRO_FOREACH_EXPAND(call, __VA_ARGS__))
        !            96: #define MACRO_RPACK(call, terminator, ...) MACRO_EXPAND(MACRO_RPACK_EXPAND(call, terminator, __VA_ARGS__))
        !            97: 
        !            98: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>