aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-03-28 23:58:25 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-03-28 23:58:25 -0700
commit2eb80c3248fc5608e6447136e06618013ac73a26 (patch)
treebd1949e2b5178d3d591dfc430790a0c7fcd36db2
parentf303567317771d66b4cff4a2cb9361647da3f3be (diff)
downloadcppawk-2eb80c3248fc5608e6447136e06618013ac73a26.tar.gz
cppawk-2eb80c3248fc5608e6447136e06618013ac73a26.tar.bz2
cppawk-2eb80c3248fc5608e6447136e06618013ac73a26.zip
narg: 16 argument safety red zone.
-rw-r--r--cppawk-include/narg-priv.h29
1 files changed, 21 insertions, 8 deletions
diff --git a/cppawk-include/narg-priv.h b/cppawk-include/narg-priv.h
index 87fb149..7dffe9d 100644
--- a/cppawk-include/narg-priv.h
+++ b/cppawk-include/narg-priv.h
@@ -32,17 +32,30 @@
#include "base.h"
#endif
-#define __narg_34(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, \
- A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, \
- A26, A27, A28, A29, A30, A31, A32, A33, N, ...) N
+#define __bad _[<"too many args"<]
-#define __xnarg_34(...) __narg_34(__VA_ARGS__)
+#define __narg_50(B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, \
+ B14, B15, B16, N33, N32, N31, N30, N29, N28, N27, N26, N25, \
+ N24, N23, N22, N21, N20, N19, N18, N17, N16, N15, N14, N13, \
+ N12, N11, N10, N9, N8, N7, N6, N5, N4, N3, N2, N1, N, ...) N
-#define __narg(...) __xnarg_34(__dummy, ## __VA_ARGS__, 32, 31, 30, 29, 28, \
- 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
- 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, \
- 3, 2, 1, 0)
+#define __xnarg_50(...) __narg_50(__VA_ARGS__)
+// The __bad entries create a 16 position red zone. We effectively have
+// space for 48 arguments, but if there are 33-48 arguments, we do not
+// return an integer count, but rather bad syntax. Beyond 48 arguments, __narg
+// starts to misbehave: it starts reproducing its 49th argument as its
+// expansion. Without the 16 position bad syntax red zone, there would be
+// and abrupt change: the macro would be good up to 32 arguments, returning the
+// 1-32 ragument count, but the 33rd argument were added, the macro would
+// misbehave badly, returning the 33rd argument, causnig a potentially
+// hard-to-find bug.
+#define __narg(...) __xnarg_50(__dummy, ## __VA_ARGS__, __bad, __bad, __bad, \
+ __bad, __bad, __bad, __bad, __bad, __bad, \
+ __bad, __bad, __bad, __bad, __bad, __bad, \
+ __bad, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, \
+ 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, \
+ 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define __repn_1(mac1, mac2, a1) \
mac1(a1)