Preprocessor macro pattern matching
To find and replace a macro expansion, define a macro whose body is a call to
BRONTO_REWRITE_MACRO(). There must be two arguments to the call. The first argument
represents the macro invocation to match and should itself be a call to before()
with an argument representing the macro to match. The other argument must be a call to
after() with an argument whose tokens will be substituted into any matching calls or
inline to replace the macro expansion with its correpsonding definition.
#define REPLACE_NULL_WITH_NULLPTR \
BRONTO_REWRITE_MACRO(before(NULL), after(nullptr))Replacements may also be defined as function-like macros whose arguments may be used in both the match and correpsonding replacement.
#define REPLACE_MAX_WITH_STD(a, b) \
BRONTO_REWRITE_MACRO(before(MAX(a, b), after(std::max(a, b))))Variadic macro functions are also supported:
#define REPLACE_MIN_WITH_STD(...) \
BRONTO_REWRITE_MACRO(before(MIN(__VA_ARGS__), after(std::min(__VA_ARGS__)))Macro arguments are the only time further replacement of the after() or inline
argument is done. In all other cases, the tokens will be used to directly replace any
matching macro expansion from the before() clause.
Additionally, rather than taking the replacement tokens from the rule itself, a rule may
specify inline as the replacement which will use the original macro
definition as the replacement for the expansion site:
#define MY_MACRO(fmt, ...) printf(fmt, __VA_OPT__(,) __VA_ARGS__)
#define INLINE_PRINTF(...) \
BRONTO_REWRITE_MACRO(before(MY_MACRO(__VA_ARGS__)), inline)before
Requirements
The single argument passed to the before() function must be a single macro
expansion to be replaced. It may be either a single token or a sequence of
tokens corresponding to a function-like macro invocation. This macro need not
have been defined yet and the rule will match any call to a macro with the
same name and arguments.
Semantics
The argument to the before() function represent the tokens to match during
macro expansion. With the exception of macro argument arising from the rule
definition itself, tokens will be matched exactly. If the replacement rule is
defined as a function-like macro with parameters, those parameters may be used
as "capture groups" where they will match any number of source tokens which
may be used in the replacement to preserve those tokens.
after
Requirements
The after() function requires only that the (possibly empty) sequence of
tokens which will replace matching macro expansions occur between balanced
parentheses.
Semantics
The tokens in the argument to after() will replace the entirety of the
matching macro expansion. Each captured macro argument will be replaced by the
tokens which comprise the corresponding argument at the original expansion
location. __VA_ARGS__ and __VA_OPT__ are also supported. Neither
token-pasting nor stringification are supported.
inline
Requirements
Rather than specifying the tokens with which to replace a matching macro
expansion, the inline token may be used. When this is used as part of a
replacement rule, the replacement tokens will be taken from the macro being
expanded. The macro body generally follows the requirements of `after()',
specifically:
- Both function-like and single-token macros are supported, but must be user-defined.
- Built-in macros like
__file__,__LINE__, or__COUNTER__are not supported. - Stringification and token pasting are not supported.
Semantics
The semantics of inline are equivalent to those of after(). The tokens
from the macro definition will be used exactly, except that macro parameters
within the expansion body will be replaced by the corresponding argument,
including both __VA_ARGS__ and __VA_OPT__.