From: git Date: Wed, 22 Apr 2026 06:36:39 +0000 (-0400) Subject: initial public commit X-Git-Url: https://git.datadissipation.net/?a=commitdiff_plain;h=5fa80785df5b023205e259d5aa709def53facbd0;p=va-opt-c.git initial public commit --- 5fa80785df5b023205e259d5aa709def53facbd0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..71124db --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +_Almost_ fully C99 compatible `##__VA_ARGS__` and `__VA_OPT__()` alternative. +The compiler needs to support empty `__VA_ARGS__` (not to C99 spec) for this to work, though +all compilers tested had no issue with that (even those with partial C99 support, like lacc) + +### Usage + +Replace `__VA_ARGS__` with `VA_OPT_C(__VA_ARGS__)`: + +``` +#define prlog(f, ...) fprintf(stderr, f, VA_OPT_C(__VA_ARGS__)) +``` diff --git a/va_opt.h b/va_opt.h new file mode 100644 index 0000000..f8f7c5e --- /dev/null +++ b/va_opt.h @@ -0,0 +1,42 @@ +#ifndef VA_OPT_H_ + #define VA_OPT_H_ 1 + /* + * Credit for a big part of the macro madness: + * Jens Gudstedt + * https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ + */ + #define I_COND_COMMA(...) , + #define I_GET_ARG_(_1, _2, ARG, ...) ARG + #define I_GET_ARG(...) I_GET_ARG_(__VA_ARGS__) + #define I_HAS_COMMA(...) I_GET_ARG_(__VA_ARGS__, 1, 0) + + #define I_ISEMPTY(...) \ + I_ISEMPTY_( \ + /* test if there is just one argument, eventually an empty \ + one */ \ + I_HAS_COMMA(__VA_ARGS__), \ + /* test if I_COND_COMMA_ together with the argument \ + adds a comma */ \ + I_HAS_COMMA(I_COND_COMMA __VA_ARGS__), \ + /* test if the argument together with a parenthesis \ + adds a comma */ \ + I_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \ + /* test if placing it between I_COND_COMMA_ and the \ + parenthesis adds a comma */ \ + I_HAS_COMMA(I_COND_COMMA __VA_ARGS__ (/*empty*/)) \ + ) + + #define I_PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4 + #define I_ISEMPTY_(_0, _1, _2, _3)\ + I_HAS_COMMA(I_PASTE5(I_IS_EMPTY_CASE_, _0, _1, _2, _3)) + #define I_IS_EMPTY_CASE_0001 , + + /* expand if empty*/ + #define I_EMPTY_T_1 + /* expand if not empty */ + #define I_EMPTY_T_0 , + + #define I_MAKE_TEST_(a) I_EMPTY_T_ ## a + #define I_MAKE_TEST(a) I_MAKE_TEST_(a) + #define VA_OPT_C(...) I_MAKE_TEST(I_ISEMPTY(I_GET_ARG(,, __VA_ARGS__))) __VA_ARGS__ +#endif