mirror of
https://git.planet-casio.com/Lephenixnoir/JustUI.git
synced 2025-01-01 06:23:38 +01:00
64 lines
2.3 KiB
C
64 lines
2.3 KiB
C
//---
|
|
// JustUI.util.preproc: Preprocessor utilities
|
|
//---
|
|
|
|
#ifndef _J_UTIL_PREPROC
|
|
#define _J_UTIL_PREPROC
|
|
|
|
/* J_REPEAT: Dispatch a partially-evaluated macro call on each arg in a list
|
|
The call `J_REPEAT(X, C, V1, ..., VN)` where `C = (C1, ..., CM)` (with the
|
|
parentheses) is equivalent to the series of calls
|
|
|
|
```
|
|
X(C1, ..., CM, V1)
|
|
X(C1, ..., CM, V2)
|
|
...
|
|
X(C1, ..., CM, VN)
|
|
```
|
|
|
|
and is used to iterate on lists. There is a size limit of N≤8. */
|
|
#define J_REPEAT1(X, C, V1, ...) \
|
|
J_CALL(X, C, V1) __VA_OPT__(J_REPEAT2(X, C, __VA_ARGS__))
|
|
#define J_REPEAT2(X, C, V2, ...) \
|
|
J_CALL(X, C, V2) __VA_OPT__(J_REPEAT3(X, C, __VA_ARGS__))
|
|
#define J_REPEAT3(X, C, V3, ...) \
|
|
J_CALL(X, C, V3) __VA_OPT__(J_REPEAT4(X, C, __VA_ARGS__))
|
|
#define J_REPEAT4(X, C, V4, ...) \
|
|
J_CALL(X, C, V4) __VA_OPT__(J_REPEAT5(X, C, __VA_ARGS__))
|
|
#define J_REPEAT5(X, C, V5, ...) \
|
|
J_CALL(X, C, V5) __VA_OPT__(J_REPEAT6(X, C, __VA_ARGS__))
|
|
#define J_REPEAT6(X, C, V6, ...) \
|
|
J_CALL(X, C, V6) __VA_OPT__(J_REPEAT7(X, C, __VA_ARGS__))
|
|
#define J_REPEAT7(X, C, V7, ...) \
|
|
J_CALL(X, C, V7) __VA_OPT__(J_REPEAT8(X, C, __VA_ARGS__))
|
|
#define J_REPEAT8(X, C, V8, ...) \
|
|
({ __VA_OPT__(_Static_assert(0, \
|
|
"J_REPEAT: too many macro arguments (maximum 8)");) \
|
|
J_CALL(X, C, V8); })
|
|
#define J_REPEAT(X, C, ...) __VA_OPT__(J_REPEAT1(X, C, __VA_ARGS__))
|
|
|
|
/* J_CALL: Perform a call to a partially evaluated macro
|
|
The call `J_CALL(X, C, A1, ..., AN)` where `C = (C1, ..., CM)` (with the
|
|
parentheses) reduces to `X(C1, ..., CM, A1, ..., AN)`, i.e. it calls the
|
|
already-partially-applied `X(C)` with further arguments. Both M=0 (`C=()`)
|
|
and N=0 (no variadic arguments) are allowed.
|
|
|
|
The main difficulty is "unfolding" `C` into the arguments of `X`. This
|
|
problem is dealt with by absorbing the parentheses into an ID-function macro
|
|
call:
|
|
|
|
```
|
|
J_ID C
|
|
~> J_ID (C1, ..., CM)
|
|
~> , C1, ..., CM
|
|
```
|
|
|
|
From there, the only subtletly is gobbling the commas. We gobble the comma
|
|
before `J_ID C` if M=0 and the comma before the other arguments if N=0. This
|
|
requires a few expansion stages. */
|
|
#define J_ID(...) __VA_OPT__(,) __VA_ARGS__
|
|
#define J_CALL3(X, ...) X(__VA_ARGS__)
|
|
#define J_CALL2(...) J_CALL3(__VA_ARGS__)
|
|
#define J_CALL(X, C, ...) J_CALL2(X J_ID C, ##__VA_ARGS__)
|
|
|
|
#endif /* _J_UTIL_PREPROC */
|