initial public commit
authorgit <redacted>
Wed, 22 Apr 2026 06:36:39 +0000 (02:36 -0400)
committergit <redacted>
Wed, 22 Apr 2026 06:36:39 +0000 (02:36 -0400)
README.md [new file with mode: 0644]
va_opt.h [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
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 (file)
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