1#version 450
2
3// side test verifies multiple rounds of argument expansion
4#define bear SecondExpansion
5#define mmmB bear
6#define mmmA(a) a
7int mmmA(mmmB);                    // mmmB -> bear, and then in mmmA(), bear -> SecondExpansion
8
9// pasting skips the first round of expansion
10#define mmcatmmdog PostPasteExpansion
11#define mmcat cat
12#define mmdog dog
13#define mmp(a,b) a## b
14int mmp(mmcat, mmdog);             // mmcat/mmdog not expanded, mmcatmmdog -> PostPasteExpansion
15
16// multi-token pre
17#define mmtokpastepre(a) a##27
18mmtokpastepre(float foo);          // should declare "float foo27;"
19
20// multi-token post
21#define mmtokpastepost(a) uni ##a
22mmtokpastepost(form float foo155); // should declare "uniform float foo155;"
23
24// non-first argument
25#define foo ShouldntExpandToThis
26#define semi ;
27#define bothpaste(a,b) a##b
28float bothpaste(foo, 719);          // should declare "float foo719;"
29#define secpaste(a,b) a bar ## b
30secpaste(uniform float, foo semi)   // should declare "uniform float barfoo;"
31
32// no args
33#define noArg fl##oat
34noArg argless;
35
36// bad location
37#define bad1 ## float
38bad1 dc1;
39#define bad2 float ##
40bad2 dc2;
41
42// multiple ##
43#define multiPaste(a, b, c) a##or##b flo##at foo##c
44multiPaste(unif, m, 875);
45
46// too long
47#define simplePaste(a,b) a##b
48// 1020 + 5 characters
49float simplePaste(ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345, 12345);
50
51// non-identifiers
52int a = simplePaste(11,12);
53
54// should work in #if as well
55#define seahorse 1
56#define sealion 0
57#define marine_animal(suffix) (sea ## suffix)
58
59#if marine_animal(horse) // should pass
60uniform float seahorse_var;
61#endif
62#if !marine_animal(lion) // should pass
63uniform float sealion_var;
64#endif
65
66// operators
67#define MAKE_OP(L, R) L ## R
68const int aop = 10;
69const int bop = 4;
70int cop = aop MAKE_OP(<, <) bop;
71bool dop = aop MAKE_OP(!,=) bop;
72
73#define MAKE_OP3(L, M, R) L ## M ## R
74
75void foo()
76{
77    int e = 16;
78    e MAKE_OP3(>,>,=) 2;
79
80    // recovery from bad op
81    bool f = e MAKE_OP(>,!) 5;
82}
83
84// arguments: should make 'uniform int argPaste2;'
85#define M_NEST(q) int q
86#define M_OUTER(p) M_NEST(p##2)
87uniform M_OUTER(argPaste);
88// should make 'uniform int argPaste20suff;'
89#define M_NEST2(q) int q ## suff
90#define M_OUTER2(p) M_NEST2(p ## 20)
91uniform M_OUTER2(argPaste);
92
93#define rec(x)##
94rec(rec())
95
96#define bax(bay)
97#define baz bax(/##)
98baz
99