summaryrefslogtreecommitdiff
path: root/tests/pp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/pp')
-rw-r--r--tests/pp/01.c6
-rw-r--r--tests/pp/01.expect1
-rw-r--r--tests/pp/02.c28
-rw-r--r--tests/pp/02.expect5
-rw-r--r--tests/pp/03.c15
-rw-r--r--tests/pp/03.expect5
-rw-r--r--tests/pp/04.c4
-rw-r--r--tests/pp/04.expect1
-rw-r--r--tests/pp/05.c7
-rw-r--r--tests/pp/05.expect3
-rw-r--r--tests/pp/06.c5
-rw-r--r--tests/pp/06.expect1
-rw-r--r--tests/pp/07.c4
-rw-r--r--tests/pp/07.expect2
-rw-r--r--tests/pp/08.c4
-rw-r--r--tests/pp/08.expect1
-rw-r--r--tests/pp/09.c4
-rw-r--r--tests/pp/09.expect1
-rw-r--r--tests/pp/10.c10
-rw-r--r--tests/pp/10.expect5
-rw-r--r--tests/pp/11.c31
-rw-r--r--tests/pp/11.expect15
-rw-r--r--tests/pp/12.S8
-rw-r--r--tests/pp/12.expect2
-rw-r--r--tests/pp/13.S6
-rw-r--r--tests/pp/13.expect2
-rw-r--r--tests/pp/14.c13
-rw-r--r--tests/pp/14.expect3
-rw-r--r--tests/pp/15.c18
-rw-r--r--tests/pp/15.expect5
-rw-r--r--tests/pp/16.c3
-rw-r--r--tests/pp/16.expect2
-rw-r--r--tests/pp/17.c14
-rw-r--r--tests/pp/17.expect6
-rw-r--r--tests/pp/18.c15
-rw-r--r--tests/pp/18.expect3
-rw-r--r--tests/pp/19.c101
-rw-r--r--tests/pp/19.expect14
-rw-r--r--tests/pp/20.c13
-rw-r--r--tests/pp/20.expect6
-rw-r--r--tests/pp/21.c36
-rw-r--r--tests/pp/21.expect8
-rw-r--r--tests/pp/Makefile49
-rw-r--r--tests/pp/pp-counter.c27
-rw-r--r--tests/pp/pp-counter.expect15
45 files changed, 527 insertions, 0 deletions
diff --git a/tests/pp/01.c b/tests/pp/01.c
new file mode 100644
index 0000000..2fc3d79
--- /dev/null
+++ b/tests/pp/01.c
@@ -0,0 +1,6 @@
+#define hash_hash # ## #
+#define mkstr(a) # a
+#define in_between(a) mkstr(a)
+#define join(c, d) in_between(c hash_hash d)
+char p[] = join(x, y);
+// char p[] = "x ## y";
diff --git a/tests/pp/01.expect b/tests/pp/01.expect
new file mode 100644
index 0000000..cf5b153
--- /dev/null
+++ b/tests/pp/01.expect
@@ -0,0 +1 @@
+char p[] = "x ## y";
diff --git a/tests/pp/02.c b/tests/pp/02.c
new file mode 100644
index 0000000..feb1254
--- /dev/null
+++ b/tests/pp/02.c
@@ -0,0 +1,28 @@
+#define x 3
+#define f(a) f(x * (a))
+#undef x
+#define x 2
+#define g f
+#define z z[0]
+#define h g(~
+#define m(a) a(w)
+#define w 0,1
+#define t(a) a
+#define p() int
+#define q(x) x
+#define r(x,y) x ## y
+#define str(x) # x
+f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
+g(x+(3,4)-w) | h 5) & m
+(f)^m(m);
+char c[2][6] = { str(hello), str() };
+/*
+ * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+ * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+ * char c[2][6] = { "hello", "" };
+ */
+#define L21 f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
+#define L22 g(x+(3,4)-w) | h 5) & m\
+(f)^m(m);
+L21
+L22
diff --git a/tests/pp/02.expect b/tests/pp/02.expect
new file mode 100644
index 0000000..8ae2eb9
--- /dev/null
+++ b/tests/pp/02.expect
@@ -0,0 +1,5 @@
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+char c[2][6] = { "hello", "" };
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
diff --git a/tests/pp/03.c b/tests/pp/03.c
new file mode 100644
index 0000000..a659245
--- /dev/null
+++ b/tests/pp/03.c
@@ -0,0 +1,15 @@
+#define str(s) # s
+#define xstr(s) str(s)
+#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
+ x ## s, x ## t)
+#define INCFILE(n) vers ## n
+#define glue(a, b) a ## b
+#define xglue(a, b) glue(a, b)
+#define HIGHLOW "hello"
+#define LOW LOW ", world"
+debug(1, 2);
+fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away
+ == 0) str(: @\n), s);
+\#include xstr(INCFILE(2).h)
+glue(HIGH, LOW);
+xglue(HIGH, LOW)
diff --git a/tests/pp/03.expect b/tests/pp/03.expect
new file mode 100644
index 0000000..44aad0a
--- /dev/null
+++ b/tests/pp/03.expect
@@ -0,0 +1,5 @@
+printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
+fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);
+\#include "vers2.h"
+"hello";
+"hello" ", world"
diff --git a/tests/pp/04.c b/tests/pp/04.c
new file mode 100644
index 0000000..0068f37
--- /dev/null
+++ b/tests/pp/04.c
@@ -0,0 +1,4 @@
+#define foobar 1
+#define C(x,y) x##y
+#define D(x) (C(x,bar))
+D(foo)
diff --git a/tests/pp/04.expect b/tests/pp/04.expect
new file mode 100644
index 0000000..7c67b01
--- /dev/null
+++ b/tests/pp/04.expect
@@ -0,0 +1 @@
+(1)
diff --git a/tests/pp/05.c b/tests/pp/05.c
new file mode 100644
index 0000000..7274941
--- /dev/null
+++ b/tests/pp/05.c
@@ -0,0 +1,7 @@
+#define t(x,y,z) x ## y ## z
+#define xxx(s) int s[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), \
+ t(10,,), t(,11,), t(,,12), t(,,) };
+
+int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
+ t(10,,), t(,11,), t(,,12), t(,,) };
+xxx(j)
diff --git a/tests/pp/05.expect b/tests/pp/05.expect
new file mode 100644
index 0000000..9f9be37
--- /dev/null
+++ b/tests/pp/05.expect
@@ -0,0 +1,3 @@
+int j[] = { 123, 45, 67, 89,
+ 10, 11, 12, };
+int j[] = { 123, 45, 67, 89, 10, 11, 12, };
diff --git a/tests/pp/06.c b/tests/pp/06.c
new file mode 100644
index 0000000..28cfdde
--- /dev/null
+++ b/tests/pp/06.c
@@ -0,0 +1,5 @@
+#define X(a,b, \
+ c,d) \
+ foo
+
+X(1,2,3,4)
diff --git a/tests/pp/06.expect b/tests/pp/06.expect
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tests/pp/06.expect
@@ -0,0 +1 @@
+foo
diff --git a/tests/pp/07.c b/tests/pp/07.c
new file mode 100644
index 0000000..b22b22b
--- /dev/null
+++ b/tests/pp/07.c
@@ -0,0 +1,4 @@
+#define a() YES
+#define b() a
+b()
+b()()
diff --git a/tests/pp/07.expect b/tests/pp/07.expect
new file mode 100644
index 0000000..ad0e20a
--- /dev/null
+++ b/tests/pp/07.expect
@@ -0,0 +1,2 @@
+a
+YES
diff --git a/tests/pp/08.c b/tests/pp/08.c
new file mode 100644
index 0000000..93018e1
--- /dev/null
+++ b/tests/pp/08.c
@@ -0,0 +1,4 @@
+// test macro expansion in arguments
+#define s_pos s_s.s_pos
+#define foo(x) (x)
+foo(hej.s_pos)
diff --git a/tests/pp/08.expect b/tests/pp/08.expect
new file mode 100644
index 0000000..2b2e3ee
--- /dev/null
+++ b/tests/pp/08.expect
@@ -0,0 +1 @@
+(hej.s_s.s_pos)
diff --git a/tests/pp/09.c b/tests/pp/09.c
new file mode 100644
index 0000000..315b297
--- /dev/null
+++ b/tests/pp/09.c
@@ -0,0 +1,4 @@
+#define C(a,b,c) a##b##c
+#define N(x,y) C(x,_,y)
+#define A_O aaaaoooo
+N(A,O)
diff --git a/tests/pp/09.expect b/tests/pp/09.expect
new file mode 100644
index 0000000..adce0f9
--- /dev/null
+++ b/tests/pp/09.expect
@@ -0,0 +1 @@
+aaaaoooo
diff --git a/tests/pp/10.c b/tests/pp/10.c
new file mode 100644
index 0000000..f180eff
--- /dev/null
+++ b/tests/pp/10.c
@@ -0,0 +1,10 @@
+#define f(x) x
+#define g(x) f(x) f(x
+#define i(x) g(x)) g(x
+#define h(x) i(x))) i(x
+#define k(x) i(x))) i(x))))
+f(x)
+g(x))
+i(x)))
+h(x))))
+k(x))))
diff --git a/tests/pp/10.expect b/tests/pp/10.expect
new file mode 100644
index 0000000..bd18e18
--- /dev/null
+++ b/tests/pp/10.expect
@@ -0,0 +1,5 @@
+x
+x x
+x x x x
+x x x x x x x x
+x x x x x x x x))))
diff --git a/tests/pp/11.c b/tests/pp/11.c
new file mode 100644
index 0000000..c0edf62
--- /dev/null
+++ b/tests/pp/11.c
@@ -0,0 +1,31 @@
+#define D1(s, ...) s
+#define D2(s, ...) s D1(__VA_ARGS__)
+#define D3(s, ...) s D2(__VA_ARGS__)
+#define D4(s, ...) s D3(__VA_ARGS__)
+
+D1(a)
+D2(a, b)
+D3(a, b, c)
+D4(a, b, c, d)
+
+x D4(a, b, c, d) y
+x D4(a, b, c) y
+x D4(a, b) y
+x D4(a) y
+x D4() y
+
+#define GNU_COMMA(X,Y...) X,## Y
+
+x GNU_COMMA(A,B,C) y
+x GNU_COMMA(A,B) y
+x GNU_COMMA(A) y
+x GNU_COMMA() y
+
+#define __sun_attr___noreturn__ __attribute__((__noreturn__))
+#define ___sun_attr_inner(__a) __sun_attr_##__a
+#define __sun_attr__(__a) ___sun_attr_inner __a
+#define __NORETURN __sun_attr__((__noreturn__))
+__NORETURN
+#define X(...)
+#define Y(...) 1 __VA_ARGS__ 2
+Y(X X() ())
diff --git a/tests/pp/11.expect b/tests/pp/11.expect
new file mode 100644
index 0000000..6b9806c
--- /dev/null
+++ b/tests/pp/11.expect
@@ -0,0 +1,15 @@
+a
+a b
+a b c
+a b c d
+x a b c d y
+x a b c y
+x a b y
+x a y
+x y
+x A,B,C y
+x A,B y
+x A y
+x y
+__attribute__((__noreturn__))
+1 2
diff --git a/tests/pp/12.S b/tests/pp/12.S
new file mode 100644
index 0000000..597ccb4
--- /dev/null
+++ b/tests/pp/12.S
@@ -0,0 +1,8 @@
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ // .previous
+
+ SRC(1: movw (%esi), %bx)
+6001:
diff --git a/tests/pp/12.expect b/tests/pp/12.expect
new file mode 100644
index 0000000..17a861c
--- /dev/null
+++ b/tests/pp/12.expect
@@ -0,0 +1,2 @@
+ 9999: 1: movw (%esi), %bx; .section __ex_table, "a"; .long 9999b, 6001f ;
+6001:
diff --git a/tests/pp/13.S b/tests/pp/13.S
new file mode 100644
index 0000000..bf0b525
--- /dev/null
+++ b/tests/pp/13.S
@@ -0,0 +1,6 @@
+# `modelist' label. Each video mode record looks like:
+#ifdef AAA
+# modelist' label. Each video mode record looks like:
+#endif
+.text
+endtext:
diff --git a/tests/pp/13.expect b/tests/pp/13.expect
new file mode 100644
index 0000000..c7a3230
--- /dev/null
+++ b/tests/pp/13.expect
@@ -0,0 +1,2 @@
+.text
+endtext:
diff --git a/tests/pp/14.c b/tests/pp/14.c
new file mode 100644
index 0000000..e15468c
--- /dev/null
+++ b/tests/pp/14.c
@@ -0,0 +1,13 @@
+#define W Z
+#define Z(X) W(X,2)
+#define Y(X) Z(X)
+#define X Y
+return X(X(1));
+
+#define P Q
+#define Q(n) P(n,2)
+return P(1);
+
+#define A (B * B)
+#define B (A + A)
+return A + B;
diff --git a/tests/pp/14.expect b/tests/pp/14.expect
new file mode 100644
index 0000000..3786044
--- /dev/null
+++ b/tests/pp/14.expect
@@ -0,0 +1,3 @@
+return Z(Z(1,2),2);
+return Q(1,2);
+return ((A + A) * (A + A)) + ((B * B) + (B * B));
diff --git a/tests/pp/15.c b/tests/pp/15.c
new file mode 100644
index 0000000..cf13f9a
--- /dev/null
+++ b/tests/pp/15.c
@@ -0,0 +1,18 @@
+// insert a space between two tokens if otherwise they
+// would form a single token when read back
+
+#define n(x) x
+
+return (n(long)n(double))d;
+return n(A)n(++)n(+)n(B);
+return n(A)n(+)n(++)n(B);
+return n(A)n(++)n(+)n(+)n(B);
+
+// not a hex float
+return n(0x1E)n(-1);
+
+// unlike gcc but correct
+// XXX: return n(x)+n(x)-n(1)+n(1)-2;
+
+// unlike gcc, but cannot appear in valid C
+// XXX: return n(x)n(x)n(1)n(2)n(x);
diff --git a/tests/pp/15.expect b/tests/pp/15.expect
new file mode 100644
index 0000000..b4f885e
--- /dev/null
+++ b/tests/pp/15.expect
@@ -0,0 +1,5 @@
+return (long double)d;
+return A+++B;
+return A+ ++B;
+return A+++ +B;
+return 0x1E -1;
diff --git a/tests/pp/16.c b/tests/pp/16.c
new file mode 100644
index 0000000..8b5b642
--- /dev/null
+++ b/tests/pp/16.c
@@ -0,0 +1,3 @@
+/* The following should warn */
+#define A ...
+#define A <<=
diff --git a/tests/pp/16.expect b/tests/pp/16.expect
new file mode 100644
index 0000000..695d6d4
--- /dev/null
+++ b/tests/pp/16.expect
@@ -0,0 +1,2 @@
+
+16.c:3: warning: A redefined
diff --git a/tests/pp/17.c b/tests/pp/17.c
new file mode 100644
index 0000000..f12196f
--- /dev/null
+++ b/tests/pp/17.c
@@ -0,0 +1,14 @@
+#define STR1(u) # u
+#define pass(a) a
+#define __ASM_REG(reg) STR1(one##reg)
+#define _ASM_DX __ASM_REG(tok)
+X162 pass(__ASM_REG(tok))
+X161 pass(_ASM_DX)
+X163 pass(STR1(one##tok))
+
+X170 pass(x ## y)
+X171 pass(x pass(##) y)
+
+#define Y(x) Z(x)
+#define X Y
+X180 return X(X(1));
diff --git a/tests/pp/17.expect b/tests/pp/17.expect
new file mode 100644
index 0000000..e95aafe
--- /dev/null
+++ b/tests/pp/17.expect
@@ -0,0 +1,6 @@
+X162 "onetok"
+X161 "onetok"
+X163 "one##tok"
+X170 x ## y
+X171 x ## y
+X180 return Z(Z(1));
diff --git a/tests/pp/18.c b/tests/pp/18.c
new file mode 100644
index 0000000..0961426
--- /dev/null
+++ b/tests/pp/18.c
@@ -0,0 +1,15 @@
+#define M_RETI_ARG27(x,y,z,aa, ...) aa
+#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__)
+#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 0, useless)
+#define M_EMPTYI_DETECT(...) 0, 1,
+#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ () )
+#define EX
+#define empty(x)
+#define fnlike(x) yeah x
+/* If the following macro is called with empty arg (X183), the use
+ of 'x' between fnlike and '(' doesn't hinder the recognition of this
+ being a further fnlike macro invocation. */
+#define usefnlike(x) fnlike x (x)
+X181 M_EMPTYI_P_C1()
+X182 M_EMPTYI_P_C1(x)
+X183 usefnlike()
diff --git a/tests/pp/18.expect b/tests/pp/18.expect
new file mode 100644
index 0000000..447a9b2
--- /dev/null
+++ b/tests/pp/18.expect
@@ -0,0 +1,3 @@
+X181 1
+X182 0
+X183 yeah
diff --git a/tests/pp/19.c b/tests/pp/19.c
new file mode 100644
index 0000000..aa91abe
--- /dev/null
+++ b/tests/pp/19.c
@@ -0,0 +1,101 @@
+#define M_C2I(a, ...) a ## __VA_ARGS__
+#define M_C(a, ...) M_C2I(a, __VA_ARGS__)
+#define M_C3I(a, b, ...) a ## b ## __VA_ARGS__
+#define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__)
+
+#define M_RETI_ARG2(a, b, ...) b
+#define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__)
+#define M_RETI_ARG27(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa, ...) aa
+#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__)
+
+#define M_TOBOOLI_0 1, 0,
+#define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless)
+
+#define M_IFI_0(true_macro, ...) __VA_ARGS__
+#define M_IFI_1(true_macro, ...) true_macro
+#define M_IF(c) M_C(M_IFI_, M_BOOL(c))
+
+#define M_FLAT(...) __VA_ARGS__
+#define M_INVI_0 1
+#define M_INVI_1 0
+#define M_INV(x) M_C(M_INVI_, x)
+
+#define M_ANDI_00 0
+#define M_ANDI_01 0
+#define M_ANDI_10 0
+#define M_ANDI_11 1
+#define M_AND(x,y) M_C3(M_ANDI_, x, y)
+
+#define M_ORI_00 0
+#define M_ORI_01 1
+#define M_ORI_10 1
+#define M_ORI_11 1
+#define M_OR(x,y) M_C3(M_ORI_, x, y)
+
+#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless)
+
+#define M_EMPTYI_DETECT(...) 0, 1,
+#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ ())
+#define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__)
+#define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () )
+#define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR(M_OR(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__)),M_EMPTYI_P_C3(__VA_ARGS__))))
+#define M_APPLY_FUNC2B(func, arg1, arg2) \
+ M_IF(M_EMPTY_P(arg2))(,func(arg1, arg2))
+#define M_MAP2B_0(func, data, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,...) \
+ M_APPLY_FUNC2B(func, data, a) M_APPLY_FUNC2B(func, data, b) M_APPLY_FUNC2B(func, data, c) \
+ M_APPLY_FUNC2B(func, data, d) M_APPLY_FUNC2B(func, data, e) M_APPLY_FUNC2B(func, data, f) \
+ M_APPLY_FUNC2B(func, data, g) M_APPLY_FUNC2B(func, data, h) M_APPLY_FUNC2B(func, data, i) \
+ M_APPLY_FUNC2B(func, data, j) M_APPLY_FUNC2B(func, data, k) M_APPLY_FUNC2B(func, data, l) \
+ M_APPLY_FUNC2B(func, data, m) M_APPLY_FUNC2B(func, data, n) M_APPLY_FUNC2B(func, data, o) \
+ M_APPLY_FUNC2B(func, data, p) M_APPLY_FUNC2B(func, data, q) M_APPLY_FUNC2B(func, data, r) \
+ M_APPLY_FUNC2B(func, data, s) M_APPLY_FUNC2B(func, data, t) M_APPLY_FUNC2B(func, data, u) \
+ M_APPLY_FUNC2B(func, data, v) M_APPLY_FUNC2B(func, data, w) M_APPLY_FUNC2B(func, data, x) \
+ M_APPLY_FUNC2B(func, data, y) M_APPLY_FUNC2B(func, data, z)
+#define M_MAP2B(f, ...) M_MAP2B_0(f, __VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , )
+#define M_INIT_INIT(a) ,a,
+
+#define M_GET_METHOD(method, method_default, ...) \
+ M_RET_ARG2 (M_MAP2B(M_C, M_C3(M_, method, _), __VA_ARGS__), method_default,)
+
+#define M_TEST_METHOD_P(method, oplist) \
+ M_BOOL(M_GET_METHOD (method, 0, M_FLAT oplist))
+
+#define TRUE 1
+#define TEST1(n) \
+ M_IF(n)(ok,nok)
+#define TEST2(op) \
+ M_TEST_METHOD_P(INIT, op)
+#define TEST3(op) \
+ M_IF(M_TEST_METHOD_P(INIT, op))(ok, nok)
+#define TEST4(op) \
+ TEST1(TEST2(op))
+#define KO(a) ((void)1)
+
+/* This checks that the various expansions that ultimately lead to
+ something like 'KO(arg,arg)', where 'KO' comes from a macro
+ expansion reducing from a large macro chain do not are regarded
+ as funclike macro invocation of KO. E.g. X93 and X94 expand to 'KO',
+ but X95 must not consume the (a,b) arguments outside the M_IF()
+ invocation to reduce the 'KO' macro to an invocation. Instead
+ X95 should reduce via M_IF(KO)(a,b) to 'a'.
+
+ The other lines here are variations on this scheme, with X1 to
+ X6 coming from the bug report at
+ http://lists.nongnu.org/archive/html/tinycc-devel/2017-07/msg00017.html */
+X92 M_IF(KO)
+X93 M_GET_METHOD(INIT, 0, INIT(KO))
+X94 M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO)))
+X95 M_IF(M_GET_METHOD(INIT, 0, INIT(KO)))(a,b)
+X96 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))
+X97 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))(ok,nok)
+X98 (M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok)
+X99 M_IF(M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok)
+// test begins
+X1 TEST1(TRUE) // ==> expect ok, get ok
+// First test with a token which is not a macro
+X2 TEST2((INIT(ok))) // ==> expect 1, get 1
+X3 TEST3((INIT(ok))) // ==> expect ok, get ok
+// Then test with a token which is a macro, but should not be expanded.
+X4 TEST2((INIT(KO))) // ==> expect 1, get 1
+X5 TEST4(INIT(KO))
+X6 TEST3((INIT(KO))) // ==> expect ok, get "error: macro 'KO' used with too many args"
diff --git a/tests/pp/19.expect b/tests/pp/19.expect
new file mode 100644
index 0000000..08c0858
--- /dev/null
+++ b/tests/pp/19.expect
@@ -0,0 +1,14 @@
+X92 M_IFI_1
+X93 KO
+X94 KO
+X95 a
+X96 M_IFI_1
+X97 ok
+X98 (1)(ok, nok)
+X99 ok
+X1 ok
+X2 1
+X3 ok
+X4 1
+X5 nok
+X6 ok
diff --git a/tests/pp/20.c b/tests/pp/20.c
new file mode 100644
index 0000000..7944d62
--- /dev/null
+++ b/tests/pp/20.c
@@ -0,0 +1,13 @@
+/* Various things I encountered while hacking the pre processor */
+#define wrap(x) x
+#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__)
+#define pr_warn(x,y) pr_warning(x,y)
+#define net_ratelimited_function(function, ...) function(__VA_ARGS__)
+X1 net_ratelimited_function(pr_warn, "pipapo", bla);
+X2 net_ratelimited_function(wrap(pr_warn), "bla", foo);
+#define two m n
+#define chain4(a,b,c,d) a ## b ## c ## d
+X2 chain4(two,o,p,q)
+X3 chain4(o,two,p,q)
+X4 chain4(o,p,two,q)
+X5 chain4(o,p,q,two)
diff --git a/tests/pp/20.expect b/tests/pp/20.expect
new file mode 100644
index 0000000..d19405d
--- /dev/null
+++ b/tests/pp/20.expect
@@ -0,0 +1,6 @@
+X1 printk(KERN_WARNING "pipapo",bla);
+X2 printk(KERN_WARNING "bla",foo);
+X2 twoopq
+X3 otwopq
+X4 optwoq
+X5 opqtwo
diff --git a/tests/pp/21.c b/tests/pp/21.c
new file mode 100644
index 0000000..1316226
--- /dev/null
+++ b/tests/pp/21.c
@@ -0,0 +1,36 @@
+/* accept 'defined' as result of substitution */
+
+----- 1 ------
+#define AAA 2
+#define BBB
+#define CCC (defined ( AAA ) && AAA > 1 && !defined BBB)
+#if !CCC
+OK
+#else
+NOT OK
+#endif
+
+----- 2 ------
+#undef BBB
+#if CCC
+OK
+#else
+NOT OK
+#endif
+
+----- 3 ------
+#define DEFINED defined
+#define DDD (DEFINED ( AAA ) && AAA > 1 && !DEFINED BBB)
+#if (DDD)
+OK
+#else
+NOT OK
+#endif
+
+----- 4 ------
+#undef AAA
+#if !(DDD)
+OK
+#else
+NOT OK
+#endif
diff --git a/tests/pp/21.expect b/tests/pp/21.expect
new file mode 100644
index 0000000..5a1376b
--- /dev/null
+++ b/tests/pp/21.expect
@@ -0,0 +1,8 @@
+----- 1 ------
+OK
+----- 2 ------
+OK
+----- 3 ------
+OK
+----- 4 ------
+OK
diff --git a/tests/pp/Makefile b/tests/pp/Makefile
new file mode 100644
index 0000000..687aa52
--- /dev/null
+++ b/tests/pp/Makefile
@@ -0,0 +1,49 @@
+#
+# credits: 01..13.c from the pcc cpp-tests suite
+#
+
+TOP = ../..
+include $(TOP)/Makefile
+SRC = $(TOPSRC)/tests/pp
+VPATH = $(SRC)
+
+files = $(patsubst %.$1,%.test,$(notdir $(wildcard $(SRC)/*.$1)))
+TESTS = $(call files,c) $(call files,S)
+
+all test : $(sort $(TESTS))
+
+DIFF_OPTS = -Nu -b -B
+
+# Filter source directory in warnings/errors (out-of-tree builds)
+FILTER = 2>&1 | sed 's,$(SRC)/,,g'
+
+%.test: %.c %.expect
+ @echo PPTest $* ...
+ -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \
+ diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \
+ && rm -f $*.output
+
+%.test: %.S %.expect
+ @echo PPTest $* ...
+ -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \
+ diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \
+ && rm -f $*.output
+
+# automatically generate .expect files with gcc:
+%.expect: # %.c
+ gcc -E -P $*.[cS] >$*.expect 2>&1
+
+# tell make not to delete
+.PRECIOUS: %.expect
+
+clean:
+ rm -f *.output
+
+02.test : DIFF_OPTS += -w
+# 15.test : DIFF_OPTS += -I"^XXX:"
+
+# diff options:
+# -b ighore space changes
+# -w ighore all whitespace
+# -B ignore blank lines
+# -I <RE> ignore lines matching RE
diff --git a/tests/pp/pp-counter.c b/tests/pp/pp-counter.c
new file mode 100644
index 0000000..3978e1a
--- /dev/null
+++ b/tests/pp/pp-counter.c
@@ -0,0 +1,27 @@
+X1 __COUNTER__
+X2 __COUNTER__
+#if __COUNTER__
+X3 __COUNTER__
+#endif
+#define pass(x) x
+#define a x __COUNTER__ y
+#define a2 pass(__COUNTER__)
+#define f(c) c __COUNTER__
+#define apply(d) d d __COUNTER__ x2 f(d) y2 __COUNTER__
+#define _paste(a,b) a ## b
+#define paste(a,b) _paste(a,b)
+#define _paste3(a,b,c) a ## b ## c
+#define doublepaste(a,b) _paste3(a,b,b)
+#define str(x) #x
+X4 a
+X5 f(a)
+X6 f(b)
+X7 f(__COUNTER__)
+X8 apply(a)
+X9 apply(f(a))
+X10 apply(__COUNTER__)
+X11 apply(a2)
+X12 str(__COUNTER__)
+X13 paste(x,__COUNTER__)
+X14 _paste(x,__COUNTER__)
+X15 doublepaste(x,__COUNTER__)
diff --git a/tests/pp/pp-counter.expect b/tests/pp/pp-counter.expect
new file mode 100644
index 0000000..02fc535
--- /dev/null
+++ b/tests/pp/pp-counter.expect
@@ -0,0 +1,15 @@
+X1 0
+X2 1
+X3 3
+X4 x 4 y
+X5 x 5 y 6
+X6 b 7
+X7 8 9
+X8 x 10 y x 10 y 11 x2 x 10 y 12 y2 13
+X9 x 14 y 15 x 14 y 15 16 x2 x 14 y 15 17 y2 18
+X10 19 19 20 x2 19 21 y2 22
+X11 23 23 24 x2 23 25 y2 26
+X12 "__COUNTER__"
+X13 x27
+X14 x__COUNTER__
+X15 x2828