mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Included are Makefile implicit rules to show the preprocessed source. When debugging something around this, it may be handy.
		
			
				
	
	
		
			99 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 
 | |
|  *	BIRD Macro Tricks
 | |
|  *
 | |
|  *	(c) 2018 Jan Maria Matejka <mq@jmq.cz>
 | |
|  *
 | |
|  *	Can be freely distributed and used under the terms of the GNU GPL.
 | |
|  *
 | |
|  *	Contains useful but dirty macro tricks:
 | |
|  *		MACRO_CONCAT(a, b)	-> concatenates a##b
 | |
|  *		MACRO_BOOL(x)		-> convert 0 to 0, anything else to 1
 | |
|  *		MACRO_IFELSE(b)(true-branch)(false-branch)
 | |
|  *					-> b shall be 0 or 1; expands to the appropriate branch
 | |
|  *		MACRO_ISEMPTY(...)	-> 1 for empty argument list, 0 otherwise
 | |
|  *		MACRO_FOREACH(func, ...)
 | |
|  *					-> calling FOREACH(func, a, b, c, d) expands to
 | |
|  *						func(a) func(b) func(c) func(d)
 | |
|  *		MACRO_RPACK(func, terminator, ...)
 | |
|  *					-> packs the list into recursive calls:
 | |
|  *						func(func(func(func(terminator, a), b), c), d)
 | |
|  */
 | |
| 
 | |
| #ifndef _BIRD_MACRO_H_
 | |
| #define _BIRD_MACRO_H_
 | |
| 
 | |
| /* What to do with args */
 | |
| #define MACRO_DROP(...)
 | |
| #define MACRO_UNPAREN(...) __VA_ARGS__
 | |
| #define MACRO_SEP(a, b, sep)  a sep b
 | |
| 
 | |
| /* Aliases for some special chars */
 | |
| #define MACRO_COMMA ,
 | |
| #define MACRO_LPAREN (
 | |
| #define MACRO_RPAREN )
 | |
| #define MACRO_LPAREN_() (
 | |
| #define MACRO_RPAREN_() )
 | |
| 
 | |
| /* Multiple expansion trick */
 | |
| #define MACRO_EXPAND0(...) __VA_ARGS__
 | |
| #define MACRO_EXPAND1(...) MACRO_EXPAND0(MACRO_EXPAND0(__VA_ARGS__))
 | |
| #define MACRO_EXPAND2(...) MACRO_EXPAND1(MACRO_EXPAND1(__VA_ARGS__))
 | |
| #define MACRO_EXPAND3(...) MACRO_EXPAND2(MACRO_EXPAND2(__VA_ARGS__))
 | |
| #define MACRO_EXPAND(...) MACRO_EXPAND3(MACRO_EXPAND3(__VA_ARGS__))
 | |
| 
 | |
| /* Deferring expansion in the expansion trick */
 | |
| #define MACRO_EMPTY()
 | |
| #define MACRO_DEFER(t) t MACRO_EMPTY()
 | |
| #define MACRO_DEFER2(t) t MACRO_EMPTY MACRO_EMPTY()()
 | |
| #define MACRO_DEFER3(t) t MACRO_EMPTY MACRO_EMPTY MACRO_EMPTY()()()
 | |
| 
 | |
| /* Token concatenation */
 | |
| #define MACRO_CONCAT(prefix, ...) prefix##__VA_ARGS__
 | |
| #define MACRO_CONCAT_AFTER(...) MACRO_CONCAT(__VA_ARGS__)
 | |
| 
 | |
| /* Get first or second argument only */
 | |
| #define MACRO_FIRST(a, ...) a
 | |
| #define MACRO_SECOND(a, b, ...) b
 | |
| #define MACRO_SECOND_OR_ZERO(...) MACRO_SECOND(__VA_ARGS__, 0,)
 | |
| 
 | |
| /* Macro Boolean auxiliary macros */
 | |
| #define MACRO_BOOL_CHECK_0 ~, 1
 | |
| #define MACRO_BOOL_NEG(x) MACRO_SECOND_OR_ZERO(MACRO_CONCAT(MACRO_BOOL_CHECK_, x))
 | |
| 
 | |
| #define MACRO_BOOL_NOT_0  1
 | |
| #define MACRO_BOOL_NOT_1  0
 | |
| 
 | |
| /* Macro Boolean negation */
 | |
| #define MACRO_NOT(x) MACRO_CONCAT(MACRO_BOOL_NOT_, x)
 | |
| 
 | |
| /* Convert anything to bool (anything -> 1, 0 -> 0) */
 | |
| #define MACRO_BOOL(x) MACRO_NOT(MACRO_BOOL_NEG(x))
 | |
| 
 | |
| /*
 | |
|  * Macro If/Else condition
 | |
|  * Usage: MACRO_IFELSE(condition)(true-branch)(false-branch)
 | |
|  * Expands to true-branch if condition is true, otherwise to false-branch.
 | |
|  */
 | |
| #define MACRO_IFELSE(b) MACRO_CONCAT(MACRO_IFELSE_, b)
 | |
| #define MACRO_IFELSE_0(...) MACRO_UNPAREN
 | |
| #define MACRO_IFELSE_1(...) __VA_ARGS__ MACRO_DROP
 | |
| 
 | |
| /* Auxiliary macros for MACRO_FOREACH */
 | |
| #define MACRO_ISLAST(...) MACRO_BOOL_NEG(MACRO_FIRST(MACRO_ISLAST_CHECK __VA_ARGS__)())
 | |
| #define MACRO_ISLAST_CHECK() 0
 | |
| 
 | |
| #define MACRO_FOREACH_EXPAND(call, a, ...) MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))(call(a))(call(a) MACRO_DEFER2(MACRO_FOREACH_PAREN)()(call, __VA_ARGS__))
 | |
| #define MACRO_FOREACH_PAREN() MACRO_FOREACH_EXPAND
 | |
| 
 | |
| #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))
 | |
| #define MACRO_RPACK_PAREN() MACRO_RPACK_EXPAND
 | |
| /*
 | |
|  * Call the first argument for each following:
 | |
|  * MACRO_FOREACH(func, a, b, c, d) expands to func(a) func(b) func(c) func(d).
 | |
|  * It supports also macros as func.
 | |
|  */
 | |
| #define MACRO_FOREACH(call, ...) MACRO_EXPAND(MACRO_FOREACH_EXPAND(call, __VA_ARGS__))
 | |
| #define MACRO_RPACK(call, terminator, ...) MACRO_EXPAND(MACRO_RPACK_EXPAND(call, terminator, __VA_ARGS__))
 | |
| 
 | |
| #endif
 |