--- /dev/null
+_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__))
+```
--- /dev/null
+#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